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