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