blob: 7d9b1fa90e42555c6e6d20d79546aeb7abdc6a17 [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
Duy Truong790f06d2013-02-13 16:38:12 -08006 * Copyright (c) 2009-2012, The Linux Foundation. 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>
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +053030#include <linux/msm_ion.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;
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +0530140 struct ion_client *client;
141 struct ion_handle *input_buff_handle;
142 struct ion_handle *output_buff_handle;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700143};
144
145struct audio_frame {
146 uint16_t frame_count_lsw;
147 uint16_t frame_count_msw;
148 uint16_t frame_length;
149 uint16_t erased_pcm;
150 unsigned char raw_bitstream[]; /* samples */
151} __attribute__((packed));
152
153struct audio_frame_nt {
154 uint16_t metadata_len;
155 uint16_t frame_count_lsw;
156 uint16_t frame_count_msw;
157 uint16_t frame_length;
158 uint16_t erased_pcm;
159 uint16_t reserved;
160 uint16_t time_stamp_dword_lsw;
161 uint16_t time_stamp_dword_msw;
162 uint16_t time_stamp_lsw;
163 uint16_t time_stamp_msw;
164 uint16_t nflag_lsw;
165 uint16_t nflag_msw;
166 unsigned char raw_bitstream[]; /* samples */
167} __attribute__((packed));
168
169struct evrc_encoded_meta_out {
170 uint16_t metadata_len;
171 uint16_t time_stamp_dword_lsw;
172 uint16_t time_stamp_dword_msw;
173 uint16_t time_stamp_lsw;
174 uint16_t time_stamp_msw;
175 uint16_t nflag_lsw;
176 uint16_t nflag_msw;
177};
178
179/* Audrec Queue command sent macro's */
180#define audrec_send_bitstreamqueue(audio, cmd, len) \
181 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
182 cmd, len)
183
184#define audrec_send_audrecqueue(audio, cmd, len) \
185 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
186 cmd, len)
187
188/* DSP command send functions */
189static int audevrc_in_enc_config(struct audio_in *audio, int enable);
190static int audevrc_in_param_config(struct audio_in *audio);
191static int audevrc_in_mem_config(struct audio_in *audio);
192static int audevrc_in_record_config(struct audio_in *audio, int enable);
193static int audevrc_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt);
194
195static void audevrc_in_get_dsp_frames(struct audio_in *audio);
196static int audpcm_config(struct audio_in *audio);
197static void audevrc_out_flush(struct audio_in *audio);
198static int audpreproc_cmd_cfg_routing_mode(struct audio_in *audio);
199static void audpreproc_pcm_send_data(struct audio_in *audio, unsigned needed);
200static void audevrc_nt_in_get_dsp_frames(struct audio_in *audio);
201
202static void audevrc_in_flush(struct audio_in *audio);
203
204static void evrc_in_listener(u32 evt_id, union auddev_evt_data *evt_payload,
205 void *private_data)
206{
207 struct audio_in *audio = (struct audio_in *) private_data;
208 unsigned long flags;
209
210 MM_DBG("evt_id = 0x%8x\n", evt_id);
211 switch (evt_id) {
212 case AUDDEV_EVT_DEV_RDY: {
213 MM_DBG("AUDDEV_EVT_DEV_RDY\n");
214 spin_lock_irqsave(&audio->dev_lock, flags);
215 audio->dev_cnt++;
216 if (!audio->in_call)
217 audio->source |= (0x1 << evt_payload->routing_id);
218 spin_unlock_irqrestore(&audio->dev_lock, flags);
219
220 if ((audio->running == 1) && (audio->enabled == 1) &&
221 (audio->mode == MSM_AUD_ENC_MODE_TUNNEL))
222 audevrc_in_record_config(audio, 1);
223 }
224 break;
225 case AUDDEV_EVT_DEV_RLS: {
226 MM_DBG("AUDDEV_EVT_DEV_RLS\n");
227 spin_lock_irqsave(&audio->dev_lock, flags);
228 audio->dev_cnt--;
229 if (!audio->in_call)
230 audio->source &= ~(0x1 << evt_payload->routing_id);
231 spin_unlock_irqrestore(&audio->dev_lock, flags);
232
233 if ((!audio->running) || (!audio->enabled))
234 break;
235
236 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
237 /* Turn of as per source */
238 if (audio->source)
239 audevrc_in_record_config(audio, 1);
240 else
241 /* Turn off all */
242 audevrc_in_record_config(audio, 0);
243 }
244 }
245 break;
246 case AUDDEV_EVT_VOICE_STATE_CHG: {
247 MM_DBG("AUDDEV_EVT_VOICE_STATE_CHG, state = %d\n",
248 evt_payload->voice_state);
249 audio->voice_state = evt_payload->voice_state;
250 if (audio->in_call && audio->running &&
251 (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)) {
252 if (audio->voice_state == VOICE_STATE_INCALL)
253 audevrc_in_record_config(audio, 1);
254 else if (audio->voice_state == VOICE_STATE_OFFCALL) {
255 audevrc_in_record_config(audio, 0);
256 wake_up(&audio->wait);
257 }
258 }
259
260 break;
261 }
262 default:
263 MM_ERR("wrong event %d\n", evt_id);
264 break;
265 }
266}
267
268/* ------------------- dsp preproc event handler--------------------- */
269static void audpreproc_dsp_event(void *data, unsigned id, void *msg)
270{
271 struct audio_in *audio = data;
272
273 switch (id) {
274 case AUDPREPROC_ERROR_MSG: {
275 struct audpreproc_err_msg *err_msg = msg;
276
277 MM_ERR("ERROR_MSG: stream id %d err idx %d\n",
278 err_msg->stream_id, err_msg->aud_preproc_err_idx);
279 /* Error case */
280 wake_up(&audio->wait_enable);
281 break;
282 }
283 case AUDPREPROC_CMD_CFG_DONE_MSG: {
284 MM_DBG("CMD_CFG_DONE_MSG \n");
285 break;
286 }
287 case AUDPREPROC_CMD_ENC_CFG_DONE_MSG: {
288 struct audpreproc_cmd_enc_cfg_done_msg *enc_cfg_msg = msg;
289
290 MM_DBG("CMD_ENC_CFG_DONE_MSG: stream id %d enc type \
291 0x%8x\n", enc_cfg_msg->stream_id,
292 enc_cfg_msg->rec_enc_type);
293 /* Encoder enable success */
294 if (enc_cfg_msg->rec_enc_type & ENCODE_ENABLE) {
295 if(audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
296 MM_DBG("routing command\n");
297 audpreproc_cmd_cfg_routing_mode(audio);
298 } else {
299 audevrc_in_param_config(audio);
300 }
301 } else { /* Encoder disable success */
302 audio->running = 0;
303 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
304 audevrc_in_record_config(audio, 0);
305 else
306 wake_up(&audio->wait_enable);
307 }
308 break;
309 }
310 case AUDPREPROC_CMD_ENC_PARAM_CFG_DONE_MSG: {
311 MM_DBG("CMD_ENC_PARAM_CFG_DONE_MSG\n");
312 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
313 audevrc_in_mem_config(audio);
314 else
315 audpcm_config(audio);
316 break;
317 }
318 case AUDPREPROC_CMD_ROUTING_MODE_DONE_MSG: {
319 struct audpreproc_cmd_routing_mode_done\
320 *routing_cfg_done_msg = msg;
321 if (routing_cfg_done_msg->configuration == 0) {
322 MM_INFO("routing configuration failed\n");
323 audio->running = 0;
324 } else
325 audevrc_in_param_config(audio);
326 break;
327 }
328 case AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG: {
329 MM_DBG("AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG \n");
330 wake_up(&audio->wait_enable);
331 break;
332 }
333 default:
334 MM_ERR("Unknown Event id %d\n", id);
335 }
336}
337
338/* ------------------- dsp audrec event handler--------------------- */
339static void audrec_dsp_event(void *data, unsigned id, size_t len,
340 void (*getevent)(void *ptr, size_t len))
341{
342 struct audio_in *audio = data;
343
344 switch (id) {
345 case AUDREC_CMD_MEM_CFG_DONE_MSG: {
346 MM_DBG("CMD_MEM_CFG_DONE MSG DONE\n");
347 audio->running = 1;
348 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
349 if ((!audio->in_call && (audio->dev_cnt > 0)) ||
350 (audio->in_call &&
351 (audio->voice_state \
352 == VOICE_STATE_INCALL)))
353 audevrc_in_record_config(audio, 1);
354 } else {
355 audpreproc_pcm_send_data(audio, 1);
356 wake_up(&audio->wait_enable);
357 }
358 break;
359 }
360 case AUDREC_FATAL_ERR_MSG: {
361 struct audrec_fatal_err_msg fatal_err_msg;
362
363 getevent(&fatal_err_msg, AUDREC_FATAL_ERR_MSG_LEN);
364 MM_ERR("FATAL_ERR_MSG: err id %d\n",
365 fatal_err_msg.audrec_err_id);
366 /* Error stop the encoder */
367 audio->stopped = 1;
368 wake_up(&audio->wait);
369 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
370 wake_up(&audio->write_wait);
371 break;
372 }
373 case AUDREC_UP_PACKET_READY_MSG: {
374 struct audrec_up_pkt_ready_msg pkt_ready_msg;
375
376 getevent(&pkt_ready_msg, AUDREC_UP_PACKET_READY_MSG_LEN);
377 MM_DBG("UP_PACKET_READY_MSG: write cnt lsw %d \
378 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
379 pkt_ready_msg.audrec_packet_write_cnt_lsw, \
380 pkt_ready_msg.audrec_packet_write_cnt_msw, \
381 pkt_ready_msg.audrec_up_prev_read_cnt_lsw, \
382 pkt_ready_msg.audrec_up_prev_read_cnt_msw);
383
384 audevrc_in_get_dsp_frames(audio);
385 break;
386 }
387 case AUDREC_CMD_PCM_BUFFER_PTR_UPDATE_ARM_TO_ENC_MSG: {
388 MM_DBG("ptr_update recieved from DSP\n");
389 audpreproc_pcm_send_data(audio, 1);
390 break;
391 }
392 case AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG: {
393 MM_ERR("AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG");
394 audevrc_in_mem_config(audio);
395 break;
396 }
397 case AUDREC_UP_NT_PACKET_READY_MSG: {
398 struct audrec_up_nt_packet_ready_msg pkt_ready_msg;
399
400 getevent(&pkt_ready_msg, AUDREC_UP_NT_PACKET_READY_MSG_LEN);
401 MM_DBG("UP_NT_PACKET_READY_MSG: write cnt lsw %d \
402 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
403 pkt_ready_msg.audrec_packetwrite_cnt_lsw, \
404 pkt_ready_msg.audrec_packetwrite_cnt_msw, \
405 pkt_ready_msg.audrec_upprev_readcount_lsw, \
406 pkt_ready_msg.audrec_upprev_readcount_msw);
407
408 audevrc_nt_in_get_dsp_frames(audio);
409 break;
410 }
411 case AUDREC_CMD_EOS_ACK_MSG: {
412 MM_DBG("eos ack recieved\n");
413 break;
414 }
415 case AUDREC_CMD_FLUSH_DONE_MSG: {
416 audio->wflush = 0;
417 audio->rflush = 0;
418 audio->flush_ack = 1;
419 wake_up(&audio->write_wait);
420 MM_DBG("flush ack recieved\n");
421 break;
422 }
423 case ADSP_MESSAGE_ID: {
424 MM_DBG("Received ADSP event:module audrectask\n");
425 break;
426 }
427 default:
428 MM_ERR("Unknown Event id %d\n", id);
429 }
430}
431
432static void audevrc_in_get_dsp_frames(struct audio_in *audio)
433{
434 struct audio_frame *frame;
435 uint32_t index;
436 unsigned long flags;
437
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 audevrc_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 audevrc_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
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_evrc_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 audevrc_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));
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +0530565 if (audio->build_id[17] == '1') {
566 cmd.cmd_id = AUDPREPROC_AUDREC_CMD_ENC_CFG_2;
567 MM_ERR("sending AUDPREPROC_AUDREC_CMD_ENC_CFG_2 command");
568 } else {
569 cmd.cmd_id = AUDPREPROC_AUDREC_CMD_ENC_CFG;
570 MM_ERR("sending AUDPREPROC_AUDREC_CMD_ENC_CFG command");
571 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700572 cmd.stream_id = audio->enc_id;
573
574 if (enable)
575 cmd.audrec_enc_type = audio->enc_type | ENCODE_ENABLE;
576 else
577 cmd.audrec_enc_type &= ~(ENCODE_ENABLE);
578
579 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
580}
581
582static int audevrc_in_param_config(struct audio_in *audio)
583{
584 struct audpreproc_audrec_cmd_parm_cfg_evrc cmd;
585
586 memset(&cmd, 0, sizeof(cmd));
587 cmd.common.cmd_id = AUDPREPROC_AUDREC_CMD_PARAM_CFG;
588 cmd.common.stream_id = audio->enc_id;
589
590 cmd.enc_min_rate = audio->cfg.min_bit_rate;
591 cmd.enc_max_rate = audio->cfg.max_bit_rate;
592 cmd.rate_modulation_cmd = 0; /* Default set to 0 */
593
594 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
595}
596
597/* To Do: msm_snddev_route_enc(audio->enc_id); */
598static int audevrc_in_record_config(struct audio_in *audio, int enable)
599{
600 struct audpreproc_afe_cmd_audio_record_cfg cmd;
601 memset(&cmd, 0, sizeof(cmd));
602 cmd.cmd_id = AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG;
603 cmd.stream_id = audio->enc_id;
604 if (enable)
605 cmd.destination_activity = AUDIO_RECORDING_TURN_ON;
606 else
607 cmd.destination_activity = AUDIO_RECORDING_TURN_OFF;
608
609 cmd.source_mix_mask = audio->source;
610 if (audio->enc_id == 2) {
611 if ((cmd.source_mix_mask &
612 INTERNAL_CODEC_TX_SOURCE_MIX_MASK) ||
613 (cmd.source_mix_mask & AUX_CODEC_TX_SOURCE_MIX_MASK) ||
614 (cmd.source_mix_mask & VOICE_UL_SOURCE_MIX_MASK) ||
615 (cmd.source_mix_mask & VOICE_DL_SOURCE_MIX_MASK)) {
616 cmd.pipe_id = SOURCE_PIPE_1;
617 }
618 if (cmd.source_mix_mask &
619 AUDPP_A2DP_PIPE_SOURCE_MIX_MASK)
620 cmd.pipe_id |= SOURCE_PIPE_0;
621 }
622 MM_DBG("stream_id %x destination_activity %x \
623 source_mix_mask %x pipe_id %x",\
624 cmd.stream_id, cmd.destination_activity,
625 cmd.source_mix_mask, cmd.pipe_id);
626 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
627}
628
629static int audevrc_in_mem_config(struct audio_in *audio)
630{
631 struct audrec_cmd_arecmem_cfg cmd;
632 uint16_t *data = (void *) audio->data;
633 int n;
634
635 memset(&cmd, 0, sizeof(cmd));
636 cmd.cmd_id = AUDREC_CMD_MEM_CFG_CMD;
637 cmd.audrec_up_pkt_intm_count = 1;
638 cmd.audrec_ext_pkt_start_addr_msw = audio->phys >> 16;
639 cmd.audrec_ext_pkt_start_addr_lsw = audio->phys;
640 cmd.audrec_ext_pkt_buf_number = FRAME_NUM;
641 MM_DBG("audio->phys = %x\n", audio->phys);
642 /* prepare buffer pointers:
643 * T:36 bytes evrc packet + 4 halfword header
644 * NT:36 bytes evrc packet + 12 halfword header
645 */
646 for (n = 0; n < FRAME_NUM; n++) {
647 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
648 audio->in[n].data = data + 4;
649 data += (FRAME_SIZE/2);
650 MM_DBG("0x%8x\n", (int)(audio->in[n].data - 8));
651 } else {
652 audio->in[n].data = data + 12;
653 data += ((EVRC_FRAME_SIZE) / 2) + 12;
654 MM_DBG("0x%8x\n", (int)(audio->in[n].data - 24));
655 }
656 }
657 return audrec_send_audrecqueue(audio, &cmd, sizeof(cmd));
658}
659
660static int audevrc_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt)
661{
662 struct up_audrec_packet_ext_ptr cmd;
663
664 memset(&cmd, 0, sizeof(cmd));
665 cmd.cmd_id = UP_AUDREC_PACKET_EXT_PTR;
666 cmd.audrec_up_curr_read_count_msw = read_cnt >> 16;
667 cmd.audrec_up_curr_read_count_lsw = read_cnt;
668
669 return audrec_send_bitstreamqueue(audio, &cmd, sizeof(cmd));
670}
671static int audevrc_flush_command(struct audio_in *audio)
672{
673 struct audrec_cmd_flush cmd;
674 MM_DBG("\n");
675 memset(&cmd, 0, sizeof(cmd));
676 cmd.cmd_id = AUDREC_CMD_FLUSH;
677 return audrec_send_audrecqueue(audio, &cmd, sizeof(cmd));
678}
679
680/* must be called with audio->lock held */
681static int audevrc_in_enable(struct audio_in *audio)
682{
683 if (audio->enabled)
684 return 0;
685
686 if (audpreproc_enable(audio->enc_id, &audpreproc_dsp_event, audio)) {
687 MM_ERR("msm_adsp_enable(audpreproc) failed\n");
688 return -ENODEV;
689 }
690
691 if (msm_adsp_enable(audio->audrec)) {
692 MM_ERR("msm_adsp_enable(audrec) failed\n");
693 audpreproc_disable(audio->enc_id, audio);
694 return -ENODEV;
695 }
696 audio->enabled = 1;
697 audevrc_in_enc_config(audio, 1);
698
699 return 0;
700}
701
702/* must be called with audio->lock held */
703static int audevrc_in_disable(struct audio_in *audio)
704{
705 if (audio->enabled) {
706 audio->enabled = 0;
707 audevrc_in_enc_config(audio, 0);
708 wake_up(&audio->wait);
709 wait_event_interruptible_timeout(audio->wait_enable,
710 audio->running == 0, 1*HZ);
711 msm_adsp_disable(audio->audrec);
712 audpreproc_disable(audio->enc_id, audio);
713 }
714 return 0;
715}
716
717static void audevrc_ioport_reset(struct audio_in *audio)
718{
719 /* Make sure read/write thread are free from
720 * sleep and knowing that system is not able
721 * to process io request at the moment
722 */
723 wake_up(&audio->write_wait);
724 mutex_lock(&audio->write_lock);
725 audevrc_in_flush(audio);
726 mutex_unlock(&audio->write_lock);
727 wake_up(&audio->wait);
728 mutex_lock(&audio->read_lock);
729 audevrc_out_flush(audio);
730 mutex_unlock(&audio->read_lock);
731}
732
733static void audevrc_in_flush(struct audio_in *audio)
734{
735 int i;
736
737 audio->dsp_cnt = 0;
738 audio->in_head = 0;
739 audio->in_tail = 0;
740 audio->in_count = 0;
741 audio->eos_ack = 0;
742 for (i = 0; i < FRAME_NUM; i++) {
743 audio->in[i].size = 0;
744 audio->in[i].read = 0;
745 }
746 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
747 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
748 atomic_set(&audio->in_bytes, 0);
749 atomic_set(&audio->in_samples, 0);
750}
751
752static void audevrc_out_flush(struct audio_in *audio)
753{
754 int i;
755
756 audio->out_head = 0;
757 audio->out_tail = 0;
758 audio->out_count = 0;
759 for (i = 0; i < OUT_FRAME_NUM; i++) {
760 audio->out[i].size = 0;
761 audio->out[i].read = 0;
762 audio->out[i].used = 0;
763 }
764}
765
766/* ------------------- device --------------------- */
767static long audevrc_in_ioctl(struct file *file,
768 unsigned int cmd, unsigned long arg)
769{
770 struct audio_in *audio = file->private_data;
771 int rc = 0;
772
773 MM_DBG("\n");
774 if (cmd == AUDIO_GET_STATS) {
775 struct msm_audio_stats stats;
776 stats.byte_count = atomic_read(&audio->in_bytes);
777 stats.sample_count = atomic_read(&audio->in_samples);
778 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
779 return -EFAULT;
780 return rc;
781 }
782
783 mutex_lock(&audio->lock);
784 switch (cmd) {
785 case AUDIO_START: {
786 uint32_t freq;
787 freq = 48000;
788 MM_DBG("AUDIO_START\n");
789 if (audio->in_call && (audio->voice_state !=
790 VOICE_STATE_INCALL)) {
791 rc = -EPERM;
792 break;
793 }
794 rc = msm_snddev_request_freq(&freq, audio->enc_id,
795 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
796 MM_DBG("sample rate configured %d\n", freq);
797 if (rc < 0) {
798 MM_DBG(" Sample rate can not be set, return code %d\n",
799 rc);
800 msm_snddev_withdraw_freq(audio->enc_id,
801 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
802 MM_DBG("msm_snddev_withdraw_freq\n");
803 break;
804 }
805 /*update aurec session info in audpreproc layer*/
806 audio->session_info.session_id = audio->enc_id;
807 audio->session_info.sampling_freq = audio->samp_rate;
808 audpreproc_update_audrec_info(&audio->session_info);
809 rc = audevrc_in_enable(audio);
810 if (!rc) {
811 rc =
812 wait_event_interruptible_timeout(audio->wait_enable,
813 audio->running != 0, 1*HZ);
814 MM_DBG("state %d rc = %d\n", audio->running, rc);
815
816 if (audio->running == 0)
817 rc = -ENODEV;
818 else
819 rc = 0;
820 }
821 audio->stopped = 0;
822 break;
823 }
824 case AUDIO_STOP: {
825 /*reset the sampling frequency information at audpreproc layer*/
826 audio->session_info.sampling_freq = 0;
827 audpreproc_update_audrec_info(&audio->session_info);
828 rc = audevrc_in_disable(audio);
829 rc = msm_snddev_withdraw_freq(audio->enc_id,
830 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
831 MM_DBG("msm_snddev_withdraw_freq\n");
832 audio->stopped = 1;
833 break;
834 }
835 case AUDIO_FLUSH: {
836 MM_DBG("AUDIO_FLUSH\n");
837 audio->rflush = 1;
838 audio->wflush = 1;
839 audevrc_ioport_reset(audio);
840 if (audio->running) {
841 audevrc_flush_command(audio);
842 rc = wait_event_interruptible(audio->write_wait,
843 !audio->wflush);
844 if (rc < 0) {
845 MM_ERR("AUDIO_FLUSH interrupted\n");
846 rc = -EINTR;
847 }
848 } else {
849 audio->rflush = 0;
850 audio->wflush = 0;
851 }
852 break;
853 }
854 case AUDIO_SET_STREAM_CONFIG: {
855 struct msm_audio_stream_config cfg;
856 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
857 rc = -EFAULT;
858 break;
859 }
860 /* Allow only single frame */
861 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
862 if (cfg.buffer_size != (FRAME_SIZE - 8)) {
863 rc = -EINVAL;
864 break;
865 }
866 } else {
867 if (cfg.buffer_size != (EVRC_FRAME_SIZE + 14)) {
868 rc = -EINVAL;
869 break;
870 }
871 }
872 audio->buffer_size = cfg.buffer_size;
873 break;
874 }
875 case AUDIO_GET_STREAM_CONFIG: {
876 struct msm_audio_stream_config cfg;
877 memset(&cfg, 0, sizeof(cfg));
878 cfg.buffer_size = audio->buffer_size;
879 cfg.buffer_count = FRAME_NUM;
880 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
881 rc = -EFAULT;
882 break;
883 }
884 case AUDIO_GET_EVRC_ENC_CONFIG: {
885 if (copy_to_user((void *) arg, &audio->cfg, sizeof(audio->cfg)))
886 rc = -EFAULT;
887 break;
888 }
889 case AUDIO_SET_EVRC_ENC_CONFIG: {
890 struct msm_audio_evrc_enc_config cfg;
891 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
892 rc = -EFAULT;
893 break;
894 }
895 MM_DBG("0X%8x, 0x%8x, 0x%8x\n", cfg.min_bit_rate,
896 cfg.max_bit_rate, cfg.cdma_rate);
897 if (cfg.min_bit_rate > CDMA_RATE_FULL || \
898 cfg.min_bit_rate < CDMA_RATE_EIGHTH) {
899 MM_ERR("invalid min bitrate\n");
900 rc = -EFAULT;
901 break;
902 }
903 if (cfg.max_bit_rate > CDMA_RATE_FULL || \
904 cfg.max_bit_rate < CDMA_RATE_EIGHTH) {
905 MM_ERR("invalid max bitrate\n");
906 rc = -EFAULT;
907 break;
908 }
909 /* Recording Does not support Erase and Blank */
910 if (cfg.cdma_rate > CDMA_RATE_FULL ||
911 cfg.cdma_rate < CDMA_RATE_EIGHTH) {
912 MM_ERR("invalid qcelp cdma rate\n");
913 rc = -EFAULT;
914 break;
915 }
916 memcpy(&audio->cfg, &cfg, sizeof(cfg));
917 break;
918 }
919 case AUDIO_GET_CONFIG: {
920 struct msm_audio_config cfg;
921 memset(&cfg, 0, sizeof(cfg));
922 cfg.buffer_size = OUT_BUFFER_SIZE;
923 cfg.buffer_count = OUT_FRAME_NUM;
924 cfg.sample_rate = audio->samp_rate;
925 cfg.channel_count = audio->channel_mode;
926 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
927 rc = -EFAULT;
928 break;
929 }
930 case AUDIO_SET_INCALL: {
931 struct msm_voicerec_mode cfg;
932 unsigned long flags;
933 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
934 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
935 rc = -EFAULT;
936 break;
937 }
938 if (cfg.rec_mode != VOC_REC_BOTH &&
939 cfg.rec_mode != VOC_REC_UPLINK &&
940 cfg.rec_mode != VOC_REC_DOWNLINK) {
941 MM_ERR("invalid rec_mode\n");
942 rc = -EINVAL;
943 break;
944 } else {
945 spin_lock_irqsave(&audio->dev_lock, flags);
946 if (cfg.rec_mode == VOC_REC_UPLINK)
947 audio->source = \
948 VOICE_UL_SOURCE_MIX_MASK;
949 else if (cfg.rec_mode == VOC_REC_DOWNLINK)
950 audio->source = \
951 VOICE_DL_SOURCE_MIX_MASK;
952 else
953 audio->source = \
954 VOICE_DL_SOURCE_MIX_MASK |
955 VOICE_UL_SOURCE_MIX_MASK ;
956 audio->in_call = 1;
957 spin_unlock_irqrestore(&audio->dev_lock, flags);
958 }
959 }
960 break;
961 }
962 case AUDIO_GET_SESSION_ID: {
963 if (copy_to_user((void *) arg, &audio->enc_id,
964 sizeof(unsigned short))) {
965 rc = -EFAULT;
966 }
967 break;
968 }
969 default:
970 rc = -EINVAL;
971 }
972 mutex_unlock(&audio->lock);
973 return rc;
974}
975
976static ssize_t audevrc_in_read(struct file *file,
977 char __user *buf,
978 size_t count, loff_t *pos)
979{
980 struct audio_in *audio = file->private_data;
981 unsigned long flags;
982 const char __user *start = buf;
983 void *data;
984 uint32_t index;
985 uint32_t size;
986 int rc = 0;
987 struct evrc_encoded_meta_out meta_field;
988 struct audio_frame_nt *nt_frame;
989 MM_DBG("count = %d\n", count);
990 mutex_lock(&audio->read_lock);
991 while (count > 0) {
992 rc = wait_event_interruptible(
993 audio->wait, (audio->in_count > 0) || audio->stopped ||
994 audio->rflush ||
995 ((audio->mode == MSM_AUD_ENC_MODE_TUNNEL) &&
996 audio->in_call && audio->running &&
997 (audio->voice_state == VOICE_STATE_OFFCALL)));
998 if (rc < 0)
999 break;
1000
1001 if (audio->rflush) {
1002 rc = -EBUSY;
1003 break;
1004 }
1005 if (audio->stopped && !audio->in_count) {
1006 MM_DBG("Driver in stop state, No more buffer to read");
1007 rc = 0;/* End of File */
1008 break;
1009 } else if ((audio->mode == MSM_AUD_ENC_MODE_TUNNEL) &&
1010 audio->in_call && audio->running &&
1011 (audio->voice_state \
1012 == VOICE_STATE_OFFCALL)) {
1013 MM_DBG("Not Permitted Voice Terminated\n");
1014 rc = -EPERM; /* Voice Call stopped */
1015 break;
1016 }
1017
1018 index = audio->in_tail;
1019 data = (uint8_t *) audio->in[index].data;
1020 size = audio->in[index].size;
1021
1022 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
1023 nt_frame = (struct audio_frame_nt *)(data -
1024 sizeof(struct audio_frame_nt));
1025 memcpy((char *)&meta_field.time_stamp_dword_lsw,
1026 (char *)&nt_frame->time_stamp_dword_lsw,
1027 (sizeof(struct evrc_encoded_meta_out) - \
1028 sizeof(uint16_t)));
1029 meta_field.metadata_len =
1030 sizeof(struct evrc_encoded_meta_out);
1031 if (copy_to_user((char *)start, (char *)&meta_field,
1032 sizeof(struct evrc_encoded_meta_out))) {
1033 rc = -EFAULT;
1034 break;
1035 }
1036 if (nt_frame->nflag_lsw & 0x0001) {
1037 MM_ERR("recieved EOS in read call\n");
1038 audio->eos_ack = 1;
1039 }
1040 buf += sizeof(struct evrc_encoded_meta_out);
1041 count -= sizeof(struct evrc_encoded_meta_out);
1042 }
1043 if (count >= size) {
1044 if (copy_to_user(buf, data, size)) {
1045 rc = -EFAULT;
1046 break;
1047 }
1048 spin_lock_irqsave(&audio->dsp_lock, flags);
1049 if (index != audio->in_tail) {
1050 /* overrun -- data is
1051 * invalid and we need to retry */
1052 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1053 continue;
1054 }
1055 audio->in[index].size = 0;
1056 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
1057 audio->in_count--;
1058 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1059 count -= size;
1060 buf += size;
1061 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)) {
1062 if (!audio->eos_ack) {
1063 MM_DBG("sending read ptr command \
1064 %d %d\n",
1065 audio->dsp_cnt,
1066 audio->in_tail);
1067 audevrc_dsp_read_buffer(audio,
1068 audio->dsp_cnt++);
1069 }
1070 }
1071 } else {
1072 MM_ERR("short read\n");
1073 break;
1074 }
1075 break;
1076 }
1077 mutex_unlock(&audio->read_lock);
1078
1079 if (buf > start)
1080 return buf - start;
1081
1082 return rc;
1083}
1084
1085static void audpreproc_pcm_send_data(struct audio_in *audio, unsigned needed)
1086{
1087 struct buffer *frame;
1088 unsigned long flags;
1089 MM_DBG("\n");
1090 spin_lock_irqsave(&audio->dsp_lock, flags);
1091 if (!audio->running)
1092 goto done;
1093
1094 if (needed && !audio->wflush) {
1095 /* We were called from the callback because the DSP
1096 * requested more data. Note that the DSP does want
1097 * more data, and if a buffer was in-flight, mark it
1098 * as available (since the DSP must now be done with
1099 * it).
1100 */
1101 audio->out_needed = 1;
1102 frame = audio->out + audio->out_tail;
1103 if (frame->used == 0xffffffff) {
1104 MM_DBG("frame %d free\n", audio->out_tail);
1105 frame->used = 0;
1106 audio->out_tail ^= 1;
1107 wake_up(&audio->write_wait);
1108 }
1109 }
1110
1111 if (audio->out_needed) {
1112 /* If the DSP currently wants data and we have a
1113 * buffer available, we will send it and reset
1114 * the needed flag. We'll mark the buffer as in-flight
1115 * so that it won't be recycled until the next buffer
1116 * is requested
1117 */
1118
1119 frame = audio->out + audio->out_tail;
1120 if (frame->used) {
1121 BUG_ON(frame->used == 0xffffffff);
1122 audpreproc_pcm_buffer_ptr_refresh(audio,
1123 audio->out_tail,
1124 frame->used);
1125 frame->used = 0xffffffff;
1126 audio->out_needed = 0;
1127 }
1128 }
1129 done:
1130 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1131}
1132
1133
Steve Mucklef132c6c2012-06-06 18:30:57 -07001134static int audevrc_in_fsync(struct file *file, loff_t ppos1, loff_t ppos2, int datasync)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001135
1136{
1137 struct audio_in *audio = file->private_data;
1138 int rc = 0;
1139
1140 MM_DBG("\n"); /* Macro prints the file name and function */
1141 if (!audio->running || (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)) {
1142 rc = -EINVAL;
1143 goto done_nolock;
1144 }
1145
1146 mutex_lock(&audio->write_lock);
1147
1148 rc = wait_event_interruptible(audio->write_wait,
1149 audio->wflush);
1150 MM_DBG("waked on by some event audio->wflush = %d\n", audio->wflush);
1151
1152 if (rc < 0)
1153 goto done;
1154 else if (audio->wflush) {
1155 rc = -EBUSY;
1156 goto done;
1157 }
1158done:
1159 mutex_unlock(&audio->write_lock);
1160done_nolock:
1161 return rc;
1162
1163}
1164
1165 int audpreproc_evrc_process_eos(struct audio_in *audio,
1166 const char __user *buf_start, unsigned short mfield_size)
1167{
1168 struct buffer *frame;
1169 int rc = 0;
1170
1171 frame = audio->out + audio->out_head;
1172
1173 rc = wait_event_interruptible(audio->write_wait,
1174 (audio->out_needed &&
1175 audio->out[0].used == 0 &&
1176 audio->out[1].used == 0)
1177 || (audio->stopped)
1178 || (audio->wflush));
1179
1180 if (rc < 0)
1181 goto done;
1182 if (audio->stopped || audio->wflush) {
1183 rc = -EBUSY;
1184 goto done;
1185 }
1186 if (copy_from_user(frame->data, buf_start, mfield_size)) {
1187 rc = -EFAULT;
1188 goto done;
1189 }
1190
1191 frame->mfield_sz = mfield_size;
1192 audio->out_head ^= 1;
1193 frame->used = mfield_size;
1194 MM_DBG("copying meta_out frame->used = %d\n", frame->used);
1195 audpreproc_pcm_send_data(audio, 0);
1196done:
1197 return rc;
1198}
1199
1200static ssize_t audevrc_in_write(struct file *file,
1201 const char __user *buf,
1202 size_t count, loff_t *pos)
1203{
1204 struct audio_in *audio = file->private_data;
1205 const char __user *start = buf;
1206 struct buffer *frame;
1207 char *cpy_ptr;
1208 int rc = 0, eos_condition = AUDPREPROC_EVRC_EOS_NONE;
1209 unsigned short mfield_size = 0;
1210 int write_count = 0;
1211 MM_DBG("cnt=%d\n", count);
1212
1213 if (count & 1)
1214 return -EINVAL;
1215
1216 if (audio->mode != MSM_AUD_ENC_MODE_NONTUNNEL)
1217 return -EINVAL;
1218
1219 mutex_lock(&audio->write_lock);
1220 frame = audio->out + audio->out_head;
1221 /* if supplied count is more than driver buffer size
1222 * then only copy driver buffer size
1223 */
1224 if (count > frame->size)
1225 count = frame->size;
1226
1227 write_count = count;
1228 cpy_ptr = frame->data;
1229 rc = wait_event_interruptible(audio->write_wait,
1230 (frame->used == 0)
1231 || (audio->stopped)
1232 || (audio->wflush));
1233 if (rc < 0)
1234 goto error;
1235
1236 if (audio->stopped || audio->wflush) {
1237 rc = -EBUSY;
1238 goto error;
1239 }
1240 if (audio->mfield) {
1241 if (buf == start) {
1242 /* Processing beginning of user buffer */
1243 if (__get_user(mfield_size,
1244 (unsigned short __user *) buf)) {
1245 rc = -EFAULT;
1246 goto error;
1247 } else if (mfield_size > count) {
1248 rc = -EINVAL;
1249 goto error;
1250 }
1251 MM_DBG("mf offset_val %x\n", mfield_size);
1252 if (copy_from_user(cpy_ptr, buf, mfield_size)) {
1253 rc = -EFAULT;
1254 goto error;
1255 }
1256 /* Check if EOS flag is set and buffer has
1257 * contains just meta field
1258 */
1259 if (cpy_ptr[AUDPREPROC_EVRC_EOS_FLG_OFFSET] &
1260 AUDPREPROC_EVRC_EOS_FLG_MASK) {
1261 eos_condition = AUDPREPROC_EVRC_EOS_SET;
1262 MM_DBG("EOS SET\n");
1263 if (mfield_size == count) {
1264 buf += mfield_size;
1265 eos_condition = 0;
1266 goto exit;
1267 } else
1268 cpy_ptr[AUDPREPROC_EVRC_EOS_FLG_OFFSET] &=
1269 ~AUDPREPROC_EVRC_EOS_FLG_MASK;
1270 }
1271 cpy_ptr += mfield_size;
1272 count -= mfield_size;
1273 buf += mfield_size;
1274 } else {
1275 mfield_size = 0;
1276 MM_DBG("continuous buffer\n");
1277 }
1278 frame->mfield_sz = mfield_size;
1279 }
1280 MM_DBG("copying the stream count = %d\n", count);
1281 if (copy_from_user(cpy_ptr, buf, count)) {
1282 rc = -EFAULT;
1283 goto error;
1284 }
1285exit:
1286 frame->used = count;
1287 audio->out_head ^= 1;
1288 if (!audio->flush_ack)
1289 audpreproc_pcm_send_data(audio, 0);
1290 else {
1291 audpreproc_pcm_send_data(audio, 1);
1292 audio->flush_ack = 0;
1293 }
1294 if (eos_condition == AUDPREPROC_EVRC_EOS_SET)
1295 rc = audpreproc_evrc_process_eos(audio, start, mfield_size);
1296 mutex_unlock(&audio->write_lock);
1297 return write_count;
1298error:
1299 mutex_unlock(&audio->write_lock);
1300 return rc;
1301}
1302
1303static int audevrc_in_release(struct inode *inode, struct file *file)
1304{
1305 struct audio_in *audio = file->private_data;
1306
1307 mutex_lock(&audio->lock);
1308 audio->in_call = 0;
1309 /* with draw frequency for session
1310 incase not stopped the driver */
1311 msm_snddev_withdraw_freq(audio->enc_id, SNDDEV_CAP_TX,
1312 AUDDEV_CLNT_ENC);
1313 auddev_unregister_evt_listner(AUDDEV_CLNT_ENC, audio->enc_id);
1314 /*reset the sampling frequency information at audpreproc layer*/
1315 audio->session_info.sampling_freq = 0;
1316 audpreproc_update_audrec_info(&audio->session_info);
1317 audevrc_in_disable(audio);
1318 audevrc_in_flush(audio);
1319 msm_adsp_put(audio->audrec);
1320 audpreproc_aenc_free(audio->enc_id);
1321 audio->audrec = NULL;
1322 audio->opened = 0;
1323 if (audio->data) {
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301324 ion_unmap_kernel(audio->client, audio->input_buff_handle);
1325 ion_free(audio->client, audio->input_buff_handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001326 audio->data = NULL;
1327 }
1328 if (audio->out_data) {
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301329 ion_unmap_kernel(audio->client, audio->output_buff_handle);
1330 ion_free(audio->client, audio->output_buff_handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001331 audio->out_data = NULL;
1332 }
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301333 ion_client_destroy(audio->client);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001334 mutex_unlock(&audio->lock);
1335 return 0;
1336}
1337
1338struct audio_in the_audio_evrc_in;
1339static int audevrc_in_open(struct inode *inode, struct file *file)
1340{
1341 struct audio_in *audio = &the_audio_evrc_in;
1342 int rc;
1343 int encid;
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301344 int len = 0;
1345 unsigned long ionflag = 0;
1346 ion_phys_addr_t addr = 0;
1347 struct ion_handle *handle = NULL;
1348 struct ion_client *client = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001349
1350 mutex_lock(&audio->lock);
1351 if (audio->opened) {
1352 rc = -EBUSY;
1353 goto done;
1354 }
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301355
1356 client = msm_ion_client_create(UINT_MAX, "Audio_EVRC_in_client");
1357 if (IS_ERR_OR_NULL(client)) {
1358 MM_ERR("Unable to create ION client\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001359 rc = -ENOMEM;
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301360 goto client_create_error;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001361 }
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301362 audio->client = client;
1363
1364 MM_DBG("allocating mem sz = %d\n", DMASZ);
1365 handle = ion_alloc(client, DMASZ, SZ_4K,
Hanumant Singh7d72bad2012-08-29 18:39:44 -07001366 ION_HEAP(ION_AUDIO_HEAP_ID), 0);
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301367 if (IS_ERR_OR_NULL(handle)) {
1368 MM_ERR("Unable to create allocate O/P buffers\n");
1369 rc = -ENOMEM;
1370 goto output_buff_alloc_error;
1371 }
1372
1373 audio->output_buff_handle = handle;
1374
1375 rc = ion_phys(client , handle, &addr, &len);
1376 if (rc) {
1377 MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
1378 (unsigned int) addr, (unsigned int) len);
1379 rc = -ENOMEM;
1380 goto output_buff_get_phys_error;
1381 } else {
1382 MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
1383 (unsigned int) addr, (unsigned int) len);
1384 }
1385 audio->phys = (int32_t)addr;
1386
1387 rc = ion_handle_get_flags(client, handle, &ionflag);
1388 if (rc) {
1389 MM_ERR("could not get flags for the handle\n");
1390 rc = -ENOMEM;
1391 goto output_buff_get_flags_error;
1392 }
1393
Mitchel Humpherys911b4b72012-09-12 14:42:50 -07001394 audio->map_v_read = ion_map_kernel(client, handle);
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301395 if (IS_ERR(audio->map_v_read)) {
1396 MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
1397 (int)audio);
1398 rc = -ENOMEM;
1399 goto output_buff_map_error;
1400 }
1401 audio->data = audio->map_v_read;
1402
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001403 MM_DBG("Memory addr = 0x%8x phy addr = 0x%8x\n",\
1404 (int) audio->data, (int) audio->phys);
1405 if ((file->f_mode & FMODE_WRITE) &&
1406 (file->f_mode & FMODE_READ)) {
1407 audio->mode = MSM_AUD_ENC_MODE_NONTUNNEL;
1408 MM_DBG("Opened for non tunnel mode encoding\n");
1409 } else if (!(file->f_mode & FMODE_WRITE) &&
1410 (file->f_mode & FMODE_READ)) {
1411 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
1412 MM_DBG("Opened for tunnel mode encoding\n");
1413 } else {
1414 MM_ERR("Invalid mode\n");
1415 rc = -EACCES;
1416 goto done;
1417 }
1418
1419 /* Settings will be re-config at AUDIO_SET_CONFIG,
1420 * but at least we need to have initial config
1421 */
1422 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
1423 audio->buffer_size = (EVRC_FRAME_SIZE + 14);
1424 else
1425 audio->buffer_size = (FRAME_SIZE - 8);
1426 audio->enc_type = ENC_TYPE_EVRC | audio->mode;
1427 audio->samp_rate = 8000;
1428 audio->channel_mode = AUDREC_CMD_MODE_MONO;
1429 audio->cfg.cdma_rate = CDMA_RATE_FULL;
1430 audio->cfg.min_bit_rate = CDMA_RATE_FULL;
1431 audio->cfg.max_bit_rate = CDMA_RATE_FULL;
1432
1433 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
1434 &audio->queue_ids);
1435 if (encid < 0) {
1436 MM_ERR("No free encoder available\n");
1437 rc = -ENODEV;
1438 goto done;
1439 }
1440 audio->enc_id = encid;
1441
1442 rc = msm_adsp_get(audio->module_name, &audio->audrec,
1443 &audrec_evrc_adsp_ops, audio);
1444
1445 if (rc) {
1446 audpreproc_aenc_free(audio->enc_id);
1447 goto done;
1448 }
1449
1450 audio->stopped = 0;
1451 audio->source = 0;
1452 audio->wflush = 0;
1453 audio->rflush = 0;
1454 audio->flush_ack = 0;
1455
1456 audevrc_in_flush(audio);
1457 audevrc_out_flush(audio);
1458
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301459 MM_DBG("allocating BUFFER_SIZE %d\n", BUFFER_SIZE);
1460 handle = ion_alloc(client, BUFFER_SIZE,
Hanumant Singh7d72bad2012-08-29 18:39:44 -07001461 SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301462 if (IS_ERR_OR_NULL(handle)) {
1463 MM_ERR("Unable to create allocate I/P buffers\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001464 rc = -ENOMEM;
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301465 goto input_buff_alloc_error;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001466 }
1467
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301468 audio->input_buff_handle = handle;
1469
1470 rc = ion_phys(client , handle, &addr, &len);
1471 if (rc) {
1472 MM_ERR("I/P buffers:Invalid phy: %x sz: %x\n",
1473 (unsigned int) addr, (unsigned int) len);
1474 rc = -ENOMEM;
1475 goto input_buff_alloc_error;
1476 } else {
1477 MM_INFO("Got valid phy: %x sz: %x\n",
1478 (unsigned int) addr,
1479 (unsigned int) len);
1480 }
1481 audio->out_phys = (int32_t)addr;
1482
1483 rc = ion_handle_get_flags(client,
1484 handle, &ionflag);
1485 if (rc) {
1486 MM_ERR("could not get flags for the handle\n");
1487 rc = -ENOMEM;
1488 goto input_buff_alloc_error;
1489 }
1490
Mitchel Humpherys911b4b72012-09-12 14:42:50 -07001491 audio->map_v_write = ion_map_kernel(client, handle);
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301492 if (IS_ERR(audio->map_v_write)) {
1493 MM_ERR("could not map write buffers\n");
1494 rc = -ENOMEM;
1495 goto input_buff_map_error;
1496 }
1497 audio->out_data = audio->map_v_write;
1498 MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
1499 (unsigned int)addr,
1500 (unsigned int)audio->out_data);
1501
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001502 /* Initialize buffer */
1503 audio->out[0].data = audio->out_data + 0;
1504 audio->out[0].addr = audio->out_phys + 0;
1505 audio->out[0].size = OUT_BUFFER_SIZE;
1506
1507 audio->out[1].data = audio->out_data + OUT_BUFFER_SIZE;
1508 audio->out[1].addr = audio->out_phys + OUT_BUFFER_SIZE;
1509 audio->out[1].size = OUT_BUFFER_SIZE;
1510
1511 MM_DBG("audio->out[0].data = %d audio->out[1].data = %d",
1512 (unsigned int)audio->out[0].data,
1513 (unsigned int)audio->out[1].data);
1514 audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS |
1515 AUDDEV_EVT_VOICE_STATE_CHG;
1516
1517 audio->voice_state = msm_get_voice_state();
1518 rc = auddev_register_evt_listner(audio->device_events,
1519 AUDDEV_CLNT_ENC, audio->enc_id,
1520 evrc_in_listener, (void *) audio);
1521 if (rc) {
1522 MM_ERR("failed to register device event listener\n");
Laura Abbott61399692012-04-30 14:25:46 -07001523 iounmap(audio->map_v_write);
Santosh Mardifdc227a2011-07-11 17:20:34 +05301524 free_contiguous_memory_by_paddr(audio->out_phys);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001525 goto evt_error;
1526 }
1527 audio->mfield = META_OUT_SIZE;
1528 file->private_data = audio;
1529 audio->opened = 1;
1530 audio->out_frame_cnt++;
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +05301531 audio->build_id = socinfo_get_build_id();
Vinay Vaka4ff52a62011-12-13 15:38:35 +05301532 MM_DBG("Modem build id = %s\n", audio->build_id);
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +05301533
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001534done:
1535 mutex_unlock(&audio->lock);
1536 return rc;
1537evt_error:
1538 msm_adsp_put(audio->audrec);
1539 audpreproc_aenc_free(audio->enc_id);
1540 mutex_unlock(&audio->lock);
Sidipotu Ashok1e4d3472012-09-05 15:36:11 +05301541input_buff_map_error:
1542 ion_free(client, audio->input_buff_handle);
1543input_buff_alloc_error:
1544 ion_unmap_kernel(client, audio->output_buff_handle);
1545output_buff_map_error:
1546output_buff_get_phys_error:
1547output_buff_get_flags_error:
1548 ion_free(client, audio->output_buff_handle);
1549output_buff_alloc_error:
1550 ion_client_destroy(client);
1551client_create_error:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001552 return rc;
1553}
1554
1555static const struct file_operations audio_in_fops = {
1556 .owner = THIS_MODULE,
1557 .open = audevrc_in_open,
1558 .release = audevrc_in_release,
1559 .read = audevrc_in_read,
1560 .write = audevrc_in_write,
1561 .fsync = audevrc_in_fsync,
1562 .unlocked_ioctl = audevrc_in_ioctl,
1563};
1564
1565struct miscdevice audio_evrc_in_misc = {
1566 .minor = MISC_DYNAMIC_MINOR,
1567 .name = "msm_evrc_in",
1568 .fops = &audio_in_fops,
1569};
1570
1571static int __init audevrc_in_init(void)
1572{
1573 mutex_init(&the_audio_evrc_in.lock);
1574 mutex_init(&the_audio_evrc_in.read_lock);
1575 spin_lock_init(&the_audio_evrc_in.dsp_lock);
1576 spin_lock_init(&the_audio_evrc_in.dev_lock);
1577 init_waitqueue_head(&the_audio_evrc_in.wait);
1578 init_waitqueue_head(&the_audio_evrc_in.wait_enable);
1579 mutex_init(&the_audio_evrc_in.write_lock);
1580 init_waitqueue_head(&the_audio_evrc_in.write_wait);
1581 return misc_register(&audio_evrc_in_misc);
1582}
1583
1584device_initcall(audevrc_in_init);