blob: 8cfa4e3c5f624d146e87e57ebfd1f1f5c7105304 [file] [log] [blame]
Manish Dewangan95ae3572011-03-15 14:58:12 +05301/* arch/arm/mach-msm/qdsp5/audio_aac_in.c
2 *
3 * aac audio input device
4 *
Duy Truong790f06d2013-02-13 16:38:12 -08005 * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
Manish Dewangan95ae3572011-03-15 14:58:12 +05306 *
7 * This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_aac_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
23#include <asm/atomic.h>
24#include <asm/ioctls.h>
25
26#include <linux/module.h>
27#include <linux/fs.h>
28#include <linux/miscdevice.h>
29#include <linux/uaccess.h>
30#include <linux/kthread.h>
31#include <linux/wait.h>
32#include <linux/dma-mapping.h>
33#include <linux/delay.h>
34#include <linux/msm_audio_aac.h>
Manish Dewangan95ae3572011-03-15 14:58:12 +053035#include <linux/memory_alloc.h>
Mitchel Humpherys1da6ebe2012-09-06 10:15:56 -070036#include <linux/msm_ion.h>
Manish Dewangan95ae3572011-03-15 14:58:12 +053037
38#include "audmgr.h"
39
40#include <mach/msm_rpcrouter.h>
41#include <mach/msm_memtypes.h>
42#include <mach/iommu.h>
Manish Dewangan95ae3572011-03-15 14:58:12 +053043#include <mach/iommu_domains.h>
44
45#include <mach/msm_adsp.h>
46#include <mach/qdsp5/qdsp5audpreproc.h>
47#include <mach/qdsp5/qdsp5audpreproccmdi.h>
48#include <mach/qdsp5/qdsp5audpreprocmsg.h>
49#include <mach/qdsp5/qdsp5audreccmdi.h>
50#include <mach/qdsp5/qdsp5audrecmsg.h>
51#include <mach/debug_mm.h>
52
53#define FRAME_HEADER_SIZE 8 /* 8 bytes frame header */
54#define NT_FRAME_HEADER_SIZE 24 /* 24 bytes frame header */
55/* FRAME_NUM must be a power of two */
56#define FRAME_NUM 8
57#define AAC_FRAME_SIZE 1536 /* 36 bytes data */
58/*Tunnel mode : 1536 bytes data + 8 byte header*/
59#define FRAME_SIZE (AAC_FRAME_SIZE + FRAME_HEADER_SIZE)
60/* 1536 bytes data + 24 meta field*/
61#define NT_FRAME_SIZE (AAC_FRAME_SIZE + NT_FRAME_HEADER_SIZE)
62#define DMASZ (FRAME_SIZE * FRAME_NUM)
63#define NT_DMASZ (NT_FRAME_SIZE * FRAME_NUM)
64#define OUT_FRAME_NUM 2
65#define OUT_BUFFER_SIZE (32 * 1024 + NT_FRAME_HEADER_SIZE)
66#define BUFFER_SIZE (OUT_BUFFER_SIZE * OUT_FRAME_NUM)
67
68#define AUDPREPROC_AAC_EOS_FLG_OFFSET 0x0A /* Offset from beginning of buffer*/
69#define AUDPREPROC_AAC_EOS_FLG_MASK 0x01
70#define AUDPREPROC_AAC_EOS_NONE 0x0 /* No EOS detected */
71#define AUDPREPROC_AAC_EOS_SET 0x1 /* EOS set in meta field */
72
73struct buffer {
74 void *data;
75 uint32_t size;
76 uint32_t read;
77 uint32_t addr;
78 uint32_t used;
79 uint32_t mfield_sz;
80};
81
82struct audio_aac_in {
83 struct buffer in[FRAME_NUM];
84
85 spinlock_t dsp_lock;
86
87 atomic_t in_bytes;
88 atomic_t in_samples;
89
90 struct mutex lock;
91 struct mutex read_lock;
92 wait_queue_head_t wait;
93 wait_queue_head_t wait_enable;
94 /*write section*/
95 struct buffer out[OUT_FRAME_NUM];
96
97 uint8_t out_head;
98 uint8_t out_tail;
99 uint8_t out_needed; /* number of buffers the dsp is waiting for */
100 uint32_t out_count;
101
102 struct mutex write_lock;
103 wait_queue_head_t write_wait;
104 int32_t out_phys; /* physical address of write buffer */
105 char *out_data;
106 int mfield; /* meta field embedded in data */
107 int wflush; /*write flush */
108 int rflush; /*read flush*/
109 int out_frame_cnt;
110
111 struct msm_adsp_module *audrec;
Manish Dewangan95ae3572011-03-15 14:58:12 +0530112
113
114 /* configuration to use on next enable */
115 uint32_t samp_rate;
116 uint32_t channel_mode;
117 uint32_t buffer_size; /* Frame size (1536 bytes) */
118 uint32_t bit_rate; /* bit rate for AAC */
119 uint32_t record_quality; /* record quality (bits/sample/channel) */
120 uint32_t enc_type; /* 1 for AAC */
121 uint32_t mode; /* T or NT Mode*/
122 uint32_t dsp_cnt;
123 uint32_t in_head; /* next buffer dsp will write */
124 uint32_t in_tail; /* next buffer read() will read */
125 uint32_t in_count; /* number of buffers available to read() */
126
127 uint32_t eos_ack;
128 uint32_t flush_ack;
129
130 const char *module_name;
131 unsigned queue_ids;
132 uint16_t enc_id; /* Session Id */
133
134 unsigned short samp_rate_index;
135 uint32_t audrec_obj_idx ;
136
137 struct audmgr audmgr;
138
139 /* data allocated for various buffers */
140 char *data;
141 dma_addr_t phys;
Laura Abbott35111d32012-04-27 18:41:48 -0700142 void *map_v_read;
143 void *map_v_write;
Manish Dewangan95ae3572011-03-15 14:58:12 +0530144
145 int opened;
146 int enabled;
147 int running;
148 int stopped; /* set when stopped, cleared on flush */
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530149 struct ion_client *client;
150 struct ion_handle *input_buff_handle;
151 struct ion_handle *output_buff_handle;
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530152
153 struct audrec_session_info session_info; /*audrec session info*/
Manish Dewangan95ae3572011-03-15 14:58:12 +0530154};
155
156struct audio_frame {
157 uint16_t frame_count_lsw;
158 uint16_t frame_count_msw;
159 uint16_t frame_length;
160 uint16_t erased_pcm;
161 unsigned char raw_bitstream[];
162} __packed;
163
164struct audio_frame_nt {
165 uint16_t metadata_len;
166 uint16_t frame_count_lsw;
167 uint16_t frame_count_msw;
168 uint16_t frame_length;
169 uint16_t erased_pcm;
170 uint16_t reserved;
171 uint16_t time_stamp_dword_lsw;
172 uint16_t time_stamp_dword_msw;
173 uint16_t time_stamp_lsw;
174 uint16_t time_stamp_msw;
175 uint16_t nflag_lsw;
176 uint16_t nflag_msw;
177 unsigned char raw_bitstream[]; /* samples */
178} __packed;
179
180struct aac_encoded_meta_out {
181 uint16_t metadata_len;
182 uint16_t time_stamp_dword_lsw;
183 uint16_t time_stamp_dword_msw;
184 uint16_t time_stamp_lsw;
185 uint16_t time_stamp_msw;
186 uint16_t nflag_lsw;
187 uint16_t nflag_msw;
188};
189
190/* Audrec Queue command sent macro's */
191#define audio_send_queue_pre(audio, cmd, len) \
192 msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
193
194#define audio_send_queue_recbs(audio, cmd, len) \
195 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
196 cmd, len)
197#define audio_send_queue_rec(audio, cmd, len) \
198 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
199 cmd, len)
200
201static int audaac_in_dsp_enable(struct audio_aac_in *audio, int enable);
202static int audaac_in_encparam_config(struct audio_aac_in *audio);
203static int audaac_in_encmem_config(struct audio_aac_in *audio);
204static int audaac_in_dsp_read_buffer(struct audio_aac_in *audio,
205 uint32_t read_cnt);
206static void audaac_in_flush(struct audio_aac_in *audio);
207
208static void audaac_in_get_dsp_frames(struct audio_aac_in *audio);
209static int audpcm_config(struct audio_aac_in *audio);
210static void audaac_out_flush(struct audio_aac_in *audio);
211static int audaac_in_routing_mode_config(struct audio_aac_in *audio);
212static void audrec_pcm_send_data(struct audio_aac_in *audio, unsigned needed);
213static void audaac_nt_in_get_dsp_frames(struct audio_aac_in *audio);
214static void audaac_in_flush(struct audio_aac_in *audio);
215
216static unsigned convert_dsp_samp_index(unsigned index)
217{
218 switch (index) {
219 case 48000: return AUDREC_CMD_SAMP_RATE_INDX_48000;
220 case 44100: return AUDREC_CMD_SAMP_RATE_INDX_44100;
221 case 32000: return AUDREC_CMD_SAMP_RATE_INDX_32000;
222 case 24000: return AUDREC_CMD_SAMP_RATE_INDX_24000;
223 case 22050: return AUDREC_CMD_SAMP_RATE_INDX_22050;
224 case 16000: return AUDREC_CMD_SAMP_RATE_INDX_16000;
225 case 12000: return AUDREC_CMD_SAMP_RATE_INDX_12000;
226 case 11025: return AUDREC_CMD_SAMP_RATE_INDX_11025;
227 case 8000: return AUDREC_CMD_SAMP_RATE_INDX_8000;
228 default: return AUDREC_CMD_SAMP_RATE_INDX_11025;
229 }
230}
231
232static unsigned convert_samp_rate(unsigned hz)
233{
234 switch (hz) {
235 case 48000: return RPC_AUD_DEF_SAMPLE_RATE_48000;
236 case 44100: return RPC_AUD_DEF_SAMPLE_RATE_44100;
237 case 32000: return RPC_AUD_DEF_SAMPLE_RATE_32000;
238 case 24000: return RPC_AUD_DEF_SAMPLE_RATE_24000;
239 case 22050: return RPC_AUD_DEF_SAMPLE_RATE_22050;
240 case 16000: return RPC_AUD_DEF_SAMPLE_RATE_16000;
241 case 12000: return RPC_AUD_DEF_SAMPLE_RATE_12000;
242 case 11025: return RPC_AUD_DEF_SAMPLE_RATE_11025;
243 case 8000: return RPC_AUD_DEF_SAMPLE_RATE_8000;
244 default: return RPC_AUD_DEF_SAMPLE_RATE_11025;
245 }
246}
247
248static unsigned convert_samp_index(unsigned index)
249{
250 switch (index) {
251 case RPC_AUD_DEF_SAMPLE_RATE_48000: return 48000;
252 case RPC_AUD_DEF_SAMPLE_RATE_44100: return 44100;
253 case RPC_AUD_DEF_SAMPLE_RATE_32000: return 32000;
254 case RPC_AUD_DEF_SAMPLE_RATE_24000: return 24000;
255 case RPC_AUD_DEF_SAMPLE_RATE_22050: return 22050;
256 case RPC_AUD_DEF_SAMPLE_RATE_16000: return 16000;
257 case RPC_AUD_DEF_SAMPLE_RATE_12000: return 12000;
258 case RPC_AUD_DEF_SAMPLE_RATE_11025: return 11025;
259 case RPC_AUD_DEF_SAMPLE_RATE_8000: return 8000;
260 default: return 11025;
261 }
262}
263
264/* Convert Bit Rate to Record Quality field of DSP */
265static unsigned int bitrate_to_record_quality(unsigned int sample_rate,
266 unsigned int channel, unsigned int bit_rate) {
267 unsigned int temp;
268
269 temp = sample_rate * channel;
270 MM_DBG(" sample rate * channel = %d\n", temp);
271 /* To represent in Q12 fixed format */
272 temp = (bit_rate * 4096) / temp;
273 MM_DBG(" Record Quality = 0x%8x\n", temp);
274 return temp;
275}
276
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530277/* ------------------- dsp --------------------- */
278static void audpre_dsp_event(void *data, unsigned id, void *event_data)
279{
280
281 uint16_t *msg = event_data;
282
283 if (!msg)
284 return;
285
286 switch (id) {
287 case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
288 MM_DBG("type %d, status_flag %d\n",\
289 msg[0], msg[1]);
290 break;
291 case AUDPREPROC_MSG_ERROR_MSG_ID:
292 MM_INFO("err_index %d\n", msg[0]);
293 break;
294 case ADSP_MESSAGE_ID:
295 MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
296 break;
297 default:
298 MM_ERR("unknown event %d\n", id);
299 }
300}
301
Manish Dewangan95ae3572011-03-15 14:58:12 +0530302/* must be called with audio->lock held */
303static int audaac_in_enable(struct audio_aac_in *audio)
304{
305 struct audmgr_config cfg;
306 int rc;
307
308 if (audio->enabled)
309 return 0;
310
311 cfg.tx_rate = audio->samp_rate;
312 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
313 cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
314 cfg.codec = RPC_AUD_DEF_CODEC_AAC;
315 cfg.snd_method = RPC_SND_METHOD_MIDI;
316
317 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
318 rc = audmgr_enable(&audio->audmgr, &cfg);
319 if (rc < 0)
320 return rc;
321
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530322 if (audpreproc_enable(audio->enc_id,
323 &audpre_dsp_event, audio)) {
324 MM_ERR("msm_adsp_enable(audpreproc) failed\n");
Manish Dewangan95ae3572011-03-15 14:58:12 +0530325 audmgr_disable(&audio->audmgr);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530326 return -ENODEV;
327 }
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530328
329 /*update aurec session info in audpreproc layer*/
330 audio->session_info.session_id = audio->enc_id;
331 audio->session_info.sampling_freq =
332 convert_samp_index(audio->samp_rate);
333 audpreproc_update_audrec_info(&audio->session_info);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530334 }
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530335
Manish Dewangan95ae3572011-03-15 14:58:12 +0530336 if (msm_adsp_enable(audio->audrec)) {
337 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530338 audpreproc_disable(audio->enc_id, audio);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530339 audmgr_disable(&audio->audmgr);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530340 }
341 MM_ERR("msm_adsp_enable(audrec) failed\n");
342 return -ENODEV;
343 }
344
345 audio->enabled = 1;
346 audaac_in_dsp_enable(audio, 1);
347
348 return 0;
349}
350
351/* must be called with audio->lock held */
352static int audaac_in_disable(struct audio_aac_in *audio)
353{
354 if (audio->enabled) {
355 audio->enabled = 0;
356
357 audaac_in_dsp_enable(audio, 0);
358
Manish Dewangan95ae3572011-03-15 14:58:12 +0530359 wait_event_interruptible_timeout(audio->wait_enable,
360 audio->running == 0, 1*HZ);
Manish Dewangan89a9f232012-02-09 17:14:40 +0530361 audio->stopped = 1;
362 wake_up(&audio->wait);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530363 msm_adsp_disable(audio->audrec);
364 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530365 audpreproc_disable(audio->enc_id, audio);
366 /*reset the sampling frequency information at
367 audpreproc layer*/
368 audio->session_info.sampling_freq = 0;
369 audpreproc_update_audrec_info(&audio->session_info);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530370 audmgr_disable(&audio->audmgr);
371 }
372 }
373 return 0;
374}
375
Manish Dewangan95ae3572011-03-15 14:58:12 +0530376static void audaac_in_get_dsp_frames(struct audio_aac_in *audio)
377{
378 struct audio_frame *frame;
379 uint32_t index;
380 unsigned long flags;
381
382 index = audio->in_head;
383
384 frame = (void *) (((char *)audio->in[index].data) -
385 sizeof(*frame));
386 spin_lock_irqsave(&audio->dsp_lock, flags);
387 audio->in[index].size = frame->frame_length;
388
389 /* statistics of read */
390 atomic_add(audio->in[index].size, &audio->in_bytes);
391 atomic_add(1, &audio->in_samples);
392
393 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
394
395 /* If overflow, move the tail index foward. */
396 if (audio->in_head == audio->in_tail) {
397 MM_ERR("Error! not able to keep up the read\n");
398 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
399 MM_ERR("in_count = %d\n", audio->in_count);
400 } else
401 audio->in_count++;
402
403 audaac_in_dsp_read_buffer(audio, audio->dsp_cnt++);
404 spin_unlock_irqrestore(&audio->dsp_lock, flags);
405
406 wake_up(&audio->wait);
407}
408
409static void audaac_nt_in_get_dsp_frames(struct audio_aac_in *audio)
410{
411 struct audio_frame_nt *nt_frame;
412 uint32_t index;
413 unsigned long flags;
414
415 index = audio->in_head;
416 nt_frame = (void *) (((char *)audio->in[index].data) - \
417 sizeof(struct audio_frame_nt));
418 spin_lock_irqsave(&audio->dsp_lock, flags);
419 audio->in[index].size = nt_frame->frame_length;
420 /* statistics of read */
421 atomic_add(audio->in[index].size, &audio->in_bytes);
422 atomic_add(1, &audio->in_samples);
423
424 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
425
426 /* If overflow, move the tail index foward. */
427 if (audio->in_head == audio->in_tail)
428 MM_DBG("Error! not able to keep up the read\n");
429 else
430 audio->in_count++;
431
432 spin_unlock_irqrestore(&audio->dsp_lock, flags);
433 wake_up(&audio->wait);
434}
435
436static int audrec_pcm_buffer_ptr_refresh(struct audio_aac_in *audio,
437 unsigned idx, unsigned len)
438{
439 struct audrec_cmd_pcm_buffer_ptr_refresh_arm_enc cmd;
440
441 if (len == NT_FRAME_HEADER_SIZE)
442 len = len / 2;
443 else
444 len = (len + NT_FRAME_HEADER_SIZE) / 2;
445 MM_DBG("len = %d\n", len);
446 memset(&cmd, 0, sizeof(cmd));
447 cmd.cmd_id = AUDREC_CMD_PCM_BUFFER_PTR_REFRESH_ARM_TO_ENC;
448 cmd.num_buffers = 1;
449 if (cmd.num_buffers == 1) {
450 cmd.buf_address_length[0] = (audio->out[idx].addr &
451 0xffff0000) >> 16;
452 cmd.buf_address_length[1] = (audio->out[idx].addr &
453 0x0000ffff);
454 cmd.buf_address_length[2] = (len & 0xffff0000) >> 16;
455 cmd.buf_address_length[3] = (len & 0x0000ffff);
456 }
457 audio->out_frame_cnt++;
458 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
459}
460
461static int audpcm_config(struct audio_aac_in *audio)
462{
463 struct audrec_cmd_pcm_cfg_arm_to_enc cmd;
464 MM_DBG("\n");
465 memset(&cmd, 0, sizeof(cmd));
466 cmd.cmd_id = AUDREC_CMD_PCM_CFG_ARM_TO_ENC;
467 cmd.config_update_flag = AUDREC_PCM_CONFIG_UPDATE_FLAG_ENABLE;
468 cmd.enable_flag = AUDREC_ENABLE_FLAG_VALUE;
469 cmd.sampling_freq = convert_samp_index(audio->samp_rate);
470 if (!audio->channel_mode)
471 cmd.channels = 1;
472 else
473 cmd.channels = 2;
474 cmd.frequency_of_intimation = 1;
475 cmd.max_number_of_buffers = OUT_FRAME_NUM;
476 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
477}
478
479static int audaac_in_routing_mode_config(struct audio_aac_in *audio)
480{
481 struct audrec_cmd_routing_mode cmd;
482
483 MM_DBG("\n");
484 memset(&cmd, 0, sizeof(cmd));
485 cmd.cmd_id = AUDREC_CMD_ROUTING_MODE;
486 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
487 cmd.routing_mode = 1;
488 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
489}
490
491static void audrec_dsp_event(void *data, unsigned id, size_t len,
492 void (*getevent)(void *ptr, size_t len))
493{
494 struct audio_aac_in *audio = NULL;
495 if (data)
496 audio = data;
497 else {
498 MM_ERR("invalid data for event %x\n", id);
499 return;
500 }
501
502 switch (id) {
503 case AUDREC_MSG_CMD_CFG_DONE_MSG: {
504 struct audrec_msg_cmd_cfg_done_msg cmd_cfg_done_msg;
505 getevent(&cmd_cfg_done_msg, AUDREC_MSG_CMD_CFG_DONE_MSG_LEN);
506 if (cmd_cfg_done_msg.audrec_enc_type & \
507 AUDREC_MSG_CFG_DONE_ENC_ENA) {
508 audio->audrec_obj_idx = cmd_cfg_done_msg.audrec_obj_idx;
509 MM_DBG("CFG ENABLED\n");
510 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
511 MM_DBG("routing command\n");
512 audaac_in_routing_mode_config(audio);
513 } else {
514 audaac_in_encmem_config(audio);
515 }
516 } else {
517 MM_DBG("CFG SLEEP\n");
518 audio->running = 0;
519 wake_up(&audio->wait_enable);
520 }
521 break;
522 }
523 case AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG: {
524 struct audrec_msg_cmd_routing_mode_done_msg \
525 routing_msg;
526 getevent(&routing_msg, AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG);
527 MM_DBG("AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG");
528 if (routing_msg.configuration == 0) {
529 MM_ERR("routing configuration failed\n");
530 audio->running = 0;
531 wake_up(&audio->wait_enable);
532 } else
533 audaac_in_encmem_config(audio);
534 break;
535 }
536 case AUDREC_MSG_CMD_AREC_MEM_CFG_DONE_MSG: {
537 MM_DBG("AREC_MEM_CFG_DONE_MSG\n");
538 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
539 audaac_in_encparam_config(audio);
540 else
541 audpcm_config(audio);
542 break;
543 }
544 case AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG: {
545 MM_DBG("AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG");
546 audaac_in_encparam_config(audio);
547 break;
548 }
549 case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
550 MM_DBG("AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG\n");
551 audio->running = 1;
552 wake_up(&audio->wait_enable);
553 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
554 audrec_pcm_send_data(audio, 1);
555 break;
556 }
557 case AUDREC_CMD_PCM_BUFFER_PTR_UPDATE_ARM_TO_ENC_MSG: {
558 MM_DBG("ptr_update recieved from DSP\n");
559 audrec_pcm_send_data(audio, 1);
560 break;
561 }
562 case AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG: {
563 struct audrec_msg_no_ext_pkt_avail_msg err_msg;
564 getevent(&err_msg, AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG_LEN);
565 MM_DBG("NO_EXT_PKT_AVAILABLE_MSG %x\n",\
566 err_msg.audrec_err_id);
567 break;
568 }
569 case AUDREC_MSG_PACKET_READY_MSG: {
570 struct audrec_msg_packet_ready_msg pkt_ready_msg;
571
572 getevent(&pkt_ready_msg, AUDREC_MSG_PACKET_READY_MSG_LEN);
573 MM_DBG("UP_PACKET_READY_MSG: write cnt msw %d \
574 write cnt lsw %d read cnt msw %d read cnt lsw %d \n",\
575 pkt_ready_msg.pkt_counter_msw, \
576 pkt_ready_msg.pkt_counter_lsw, \
577 pkt_ready_msg.pkt_read_cnt_msw, \
578 pkt_ready_msg.pkt_read_cnt_lsw);
579
580 audaac_in_get_dsp_frames(audio);
581 break;
582 }
583 case AUDREC_UP_NT_PACKET_READY_MSG: {
584 struct audrec_up_nt_packet_ready_msg pkt_ready_msg;
585
586 getevent(&pkt_ready_msg, AUDREC_UP_NT_PACKET_READY_MSG_LEN);
587 MM_DBG("UP_NT_PACKET_READY_MSG: write cnt lsw %d \
588 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
589 pkt_ready_msg.audrec_packetwrite_cnt_lsw, \
590 pkt_ready_msg.audrec_packetwrite_cnt_msw, \
591 pkt_ready_msg.audrec_upprev_readcount_lsw, \
592 pkt_ready_msg.audrec_upprev_readcount_msw);
593
594 audaac_nt_in_get_dsp_frames(audio);
595 break;
596 }
597 case AUDREC_CMD_FLUSH_DONE_MSG: {
598 audio->wflush = 0;
599 audio->rflush = 0;
600 audio->flush_ack = 1;
601 wake_up(&audio->write_wait);
602 MM_DBG("flush ack recieved\n");
603 break;
604 }
605 case ADSP_MESSAGE_ID:
606 MM_DBG("Received ADSP event: module \
607 enable/disable(audrectask)\n");
608 break;
609 default:
610 MM_ERR("unknown event %d\n", id);
611 }
612}
613
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530614static struct msm_adsp_ops audrec_aac_adsp_ops = {
Manish Dewangan95ae3572011-03-15 14:58:12 +0530615 .event = audrec_dsp_event,
616};
617
618static int audaac_in_dsp_enable(struct audio_aac_in *audio, int enable)
619{
620 struct audrec_cmd_enc_cfg cmd;
621
622 memset(&cmd, 0, sizeof(cmd));
623 cmd.cmd_id = AUDREC_CMD_ENC_CFG;
624 cmd.audrec_enc_type = (audio->enc_type & 0xFF) |
625 (enable ? AUDREC_CMD_ENC_ENA : AUDREC_CMD_ENC_DIS);
626 /* Don't care */
627 cmd.audrec_obj_idx = audio->audrec_obj_idx;
628
629 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
630}
631
632static int audaac_in_encmem_config(struct audio_aac_in *audio)
633{
634 struct audrec_cmd_arecmem_cfg cmd;
635 uint16_t *data = (void *) audio->data;
636 int n;
637 int header_len = 0;
638
639 memset(&cmd, 0, sizeof(cmd));
640
641 cmd.cmd_id = AUDREC_CMD_ARECMEM_CFG;
642 cmd.audrec_obj_idx = audio->audrec_obj_idx;
643 /* Rate at which packet complete message comes */
644 cmd.audrec_up_pkt_intm_cnt = 1;
645 cmd.audrec_extpkt_buffer_msw = audio->phys >> 16;
646 cmd.audrec_extpkt_buffer_lsw = audio->phys;
647 /* Max Buffer no available for frames */
648 cmd.audrec_extpkt_buffer_num = FRAME_NUM;
649
650 /* prepare buffer pointers:
651 * T:1536 bytes aac packet + 4 halfword header
652 * NT:1536 bytes aac packet + 12 halfword header
653 */
654 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
655 header_len = FRAME_HEADER_SIZE/2;
656 else
657 header_len = NT_FRAME_HEADER_SIZE/2;
658
659 for (n = 0; n < FRAME_NUM; n++) {
660 audio->in[n].data = data + header_len;
661 data += (AAC_FRAME_SIZE/2) + header_len;
662 MM_DBG("0x%8x\n", (int)(audio->in[n].data - header_len*2));
663 }
664
665 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
666}
667
668static int audaac_in_encparam_config(struct audio_aac_in *audio)
669{
670 struct audrec_cmd_arecparam_aac_cfg cmd;
671
672 memset(&cmd, 0, sizeof(cmd));
673 cmd.common.cmd_id = AUDREC_CMD_ARECPARAM_CFG;
674 cmd.common.audrec_obj_idx = audio->audrec_obj_idx;
675 cmd.samp_rate_idx = audio->samp_rate_index;
676 cmd.stereo_mode = audio->channel_mode;
677 cmd.rec_quality = audio->record_quality;
678
679
680 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
681}
682
683static int audaac_flush_command(struct audio_aac_in *audio)
684{
685 struct audrec_cmd_flush cmd;
686 MM_DBG("\n");
687 memset(&cmd, 0, sizeof(cmd));
688 cmd.cmd_id = AUDREC_CMD_FLUSH;
689 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
690}
691
692static int audaac_in_dsp_read_buffer(struct audio_aac_in *audio,
693 uint32_t read_cnt)
694{
695 audrec_cmd_packet_ext_ptr cmd;
696
697 memset(&cmd, 0, sizeof(cmd));
698 cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
699 cmd.type = audio->audrec_obj_idx;
700 cmd.curr_rec_count_msw = read_cnt >> 16;
701 cmd.curr_rec_count_lsw = read_cnt;
702
703 return audio_send_queue_recbs(audio, &cmd, sizeof(cmd));
704}
705
706/* ------------------- device --------------------- */
707
708static void audaac_ioport_reset(struct audio_aac_in *audio)
709{
710 /* Make sure read/write thread are free from
711 * sleep and knowing that system is not able
712 * to process io request at the moment
713 */
Manish Dewangan95ae3572011-03-15 14:58:12 +0530714 wake_up(&audio->wait);
715 mutex_lock(&audio->read_lock);
Manish Dewangana4f1df02012-02-08 17:06:54 +0530716 audaac_in_flush(audio);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530717 mutex_unlock(&audio->read_lock);
Manish Dewangana4f1df02012-02-08 17:06:54 +0530718 wake_up(&audio->write_wait);
719 mutex_lock(&audio->write_lock);
720 audaac_out_flush(audio);
721 mutex_unlock(&audio->write_lock);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530722}
723
724static void audaac_in_flush(struct audio_aac_in *audio)
725{
726 int i;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530727 unsigned long flags;
Manish Dewangan95ae3572011-03-15 14:58:12 +0530728
729 audio->dsp_cnt = 0;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530730 spin_lock_irqsave(&audio->dsp_lock, flags);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530731 audio->in_head = 0;
732 audio->in_tail = 0;
733 audio->in_count = 0;
734 audio->eos_ack = 0;
735 for (i = FRAME_NUM-1; i >= 0; i--) {
736 audio->in[i].size = 0;
737 audio->in[i].read = 0;
738 }
Manish Dewangana4f1df02012-02-08 17:06:54 +0530739 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530740 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
741 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
742 atomic_set(&audio->in_bytes, 0);
743 atomic_set(&audio->in_samples, 0);
744}
745
746static void audaac_out_flush(struct audio_aac_in *audio)
747{
748 int i;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530749 unsigned long flags;
Manish Dewangan95ae3572011-03-15 14:58:12 +0530750
751 audio->out_head = 0;
Manish Dewangan95ae3572011-03-15 14:58:12 +0530752 audio->out_count = 0;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530753 spin_lock_irqsave(&audio->dsp_lock, flags);
754 audio->out_tail = 0;
Manish Dewangan95ae3572011-03-15 14:58:12 +0530755 for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
756 audio->out[i].size = 0;
757 audio->out[i].read = 0;
758 audio->out[i].used = 0;
759 }
Manish Dewangana4f1df02012-02-08 17:06:54 +0530760 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530761}
762
763/* ------------------- device --------------------- */
764static long audaac_in_ioctl(struct file *file,
765 unsigned int cmd, unsigned long arg)
766{
767 struct audio_aac_in *audio = file->private_data;
768 int rc = 0;
769
770 MM_DBG("\n");
771 if (cmd == AUDIO_GET_STATS) {
772 struct msm_audio_stats stats;
773 stats.byte_count = atomic_read(&audio->in_bytes);
774 stats.sample_count = atomic_read(&audio->in_samples);
775 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
776 return -EFAULT;
777 return rc;
778 }
779
780 mutex_lock(&audio->lock);
781 switch (cmd) {
782 case AUDIO_START: {
783 rc = audaac_in_enable(audio);
784 if (!rc) {
785 rc =
786 wait_event_interruptible_timeout(audio->wait_enable,
787 audio->running != 0, 1*HZ);
788 MM_DBG("state %d rc = %d\n", audio->running, rc);
789
790 if (audio->running == 0)
791 rc = -ENODEV;
792 else
793 rc = 0;
794 }
795 audio->stopped = 0;
796 break;
797 }
798 case AUDIO_STOP: {
799 rc = audaac_in_disable(audio);
Manish Dewangan95ae3572011-03-15 14:58:12 +0530800 break;
801 }
802 case AUDIO_FLUSH: {
803 MM_DBG("AUDIO_FLUSH\n");
804 audio->rflush = 1;
805 audio->wflush = 1;
806 audaac_ioport_reset(audio);
807 if (audio->running) {
808 audaac_flush_command(audio);
809 rc = wait_event_interruptible(audio->write_wait,
810 !audio->wflush);
811 if (rc < 0) {
812 MM_ERR("AUDIO_FLUSH interrupted\n");
813 rc = -EINTR;
814 }
815 } else {
816 audio->rflush = 0;
817 audio->wflush = 0;
818 }
819 break;
820 }
821 case AUDIO_GET_CONFIG: {
822 struct msm_audio_config cfg;
823 memset(&cfg, 0, sizeof(cfg));
824 cfg.buffer_size = OUT_BUFFER_SIZE;
825 cfg.buffer_count = OUT_FRAME_NUM;
826 cfg.sample_rate = convert_samp_index(audio->samp_rate);
827 cfg.channel_count = 1;
828 cfg.type = 0;
829 cfg.unused[0] = 0;
830 cfg.unused[1] = 0;
831 cfg.unused[2] = 0;
832 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
833 rc = -EFAULT;
834 else
835 rc = 0;
836 break;
837 }
838 case AUDIO_GET_STREAM_CONFIG: {
839 struct msm_audio_stream_config cfg;
840 memset(&cfg, 0, sizeof(cfg));
841 cfg.buffer_size = audio->buffer_size;
842 cfg.buffer_count = FRAME_NUM;
843 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
844 rc = -EFAULT;
845 else
846 rc = 0;
847 break;
848 }
849 case AUDIO_SET_STREAM_CONFIG: {
850 struct msm_audio_stream_config cfg;
851 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
852 rc = -EFAULT;
853 break;
854 }
855 /* Allow only single frame */
856 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
857 if (cfg.buffer_size != (FRAME_SIZE - 8))
858 rc = -EINVAL;
859 break;
860 } else {
861 if (cfg.buffer_size != (AAC_FRAME_SIZE + 14))
862 rc = -EINVAL;
863 break;
864 }
865 audio->buffer_size = cfg.buffer_size;
866 break;
867 }
868 case AUDIO_GET_AAC_ENC_CONFIG: {
869 struct msm_audio_aac_enc_config cfg;
870 if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO)
871 cfg.channels = 1;
872 else
873 cfg.channels = 2;
874 cfg.sample_rate = convert_samp_index(audio->samp_rate);
875 cfg.bit_rate = audio->bit_rate;
876 cfg.stream_format = AUDIO_AAC_FORMAT_RAW;
877 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
878 rc = -EFAULT;
879 break;
880 }
881 case AUDIO_SET_AAC_ENC_CONFIG: {
882 struct msm_audio_aac_enc_config cfg;
883 unsigned int record_quality;
884 if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
885 rc = -EFAULT;
886 break;
887 }
888 if (cfg.stream_format != AUDIO_AAC_FORMAT_RAW) {
889 MM_ERR("unsupported AAC format\n");
890 rc = -EINVAL;
891 break;
892 }
893 record_quality = bitrate_to_record_quality(cfg.sample_rate,
894 cfg.channels, cfg.bit_rate);
895 /* Range of Record Quality Supported by DSP, Q12 format */
896 if ((record_quality < 0x800) || (record_quality > 0x4000)) {
897 MM_ERR("Unsupported bit rate\n");
898 rc = -EINVAL;
899 break;
900 }
901 MM_DBG("channels = %d\n", cfg.channels);
902 if (cfg.channels == 1) {
903 cfg.channels = AUDREC_CMD_STEREO_MODE_MONO;
904 } else if (cfg.channels == 2) {
905 cfg.channels = AUDREC_CMD_STEREO_MODE_STEREO;
906 } else {
907 rc = -EINVAL;
908 break;
909 }
910
911 audio->samp_rate = convert_samp_rate(cfg.sample_rate);
912 audio->samp_rate_index =
913 convert_dsp_samp_index(cfg.sample_rate);
914 audio->channel_mode = cfg.channels;
915 audio->bit_rate = cfg.bit_rate;
916 audio->record_quality = record_quality;
917 MM_DBG(" Record Quality = 0x%8x\n", audio->record_quality);
918 break;
919 }
920
921 default:
922 rc = -EINVAL;
923 }
924 mutex_unlock(&audio->lock);
925 return rc;
926}
927
928static ssize_t audaac_in_read(struct file *file,
929 char __user *buf,
930 size_t count, loff_t *pos)
931{
932 struct audio_aac_in *audio = file->private_data;
933 unsigned long flags;
934 const char __user *start = buf;
935 void *data;
936 uint32_t index;
937 uint32_t size;
938 int rc = 0;
939 struct aac_encoded_meta_out meta_field;
940 struct audio_frame_nt *nt_frame;
941 MM_DBG("count = %d\n", count);
942 mutex_lock(&audio->read_lock);
943 while (count > 0) {
944 rc = wait_event_interruptible(
945 audio->wait, (audio->in_count > 0) || audio->stopped ||
946 audio->rflush);
947 if (rc < 0)
948 break;
949
950 if (audio->rflush) {
951 rc = -EBUSY;
952 break;
953 }
954 if (audio->stopped && !audio->in_count) {
955 MM_DBG("Driver in stop state, No more buffer to read");
956 rc = 0;/* End of File */
957 break;
958 }
959
960 index = audio->in_tail;
961 data = (uint8_t *) audio->in[index].data;
962 size = audio->in[index].size;
963
964 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
965 nt_frame = (struct audio_frame_nt *)(data -
966 sizeof(struct audio_frame_nt));
967 memcpy((char *)&meta_field.time_stamp_dword_lsw,
968 (char *)&nt_frame->time_stamp_dword_lsw,
969 (sizeof(struct aac_encoded_meta_out) - \
970 sizeof(uint16_t)));
971 meta_field.metadata_len =
972 sizeof(struct aac_encoded_meta_out);
973 if (copy_to_user((char *)start, (char *)&meta_field,
974 sizeof(struct aac_encoded_meta_out))) {
975 rc = -EFAULT;
976 break;
977 }
978 if (nt_frame->nflag_lsw & 0x0001) {
979 MM_DBG("recieved EOS in read call\n");
980 audio->eos_ack = 1;
981 }
982 buf += sizeof(struct aac_encoded_meta_out);
983 count -= sizeof(struct aac_encoded_meta_out);
984 }
985 if (count >= size) {
986 /* order the reads on the buffer */
987 dma_coherent_post_ops();
988 if (copy_to_user(buf, data, size)) {
989 rc = -EFAULT;
990 break;
991 }
992 spin_lock_irqsave(&audio->dsp_lock, flags);
993 if (index != audio->in_tail) {
994 /* overrun -- data is
995 * invalid and we need to retry */
996 spin_unlock_irqrestore(&audio->dsp_lock, flags);
997 continue;
998 }
999 audio->in[index].size = 0;
1000 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
1001 audio->in_count--;
1002 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1003 count -= size;
1004 buf += size;
1005 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)) {
1006 if (!audio->eos_ack) {
1007 MM_DBG("sending read ptr command \
1008 %d %d\n",
1009 audio->dsp_cnt,
1010 audio->in_tail);
1011 audaac_in_dsp_read_buffer(audio,
1012 audio->dsp_cnt++);
1013 }
1014 }
1015 } else {
1016 MM_ERR("short read\n");
1017 break;
1018 }
1019 break;
1020 }
1021 mutex_unlock(&audio->read_lock);
1022
1023 if (buf > start)
1024 return buf - start;
1025
1026 return rc;
1027}
1028
1029static void audrec_pcm_send_data(struct audio_aac_in *audio, unsigned needed)
1030{
1031 struct buffer *frame;
1032 unsigned long flags;
1033 MM_DBG("\n");
1034 spin_lock_irqsave(&audio->dsp_lock, flags);
1035 if (!audio->running)
1036 goto done;
1037
1038 if (needed && !audio->wflush) {
1039 /* We were called from the callback because the DSP
1040 * requested more data. Note that the DSP does want
1041 * more data, and if a buffer was in-flight, mark it
1042 * as available (since the DSP must now be done with
1043 * it).
1044 */
1045 audio->out_needed = 1;
1046 frame = audio->out + audio->out_tail;
1047 if (frame->used == 0xffffffff) {
1048 MM_DBG("frame %d free\n", audio->out_tail);
1049 frame->used = 0;
1050 audio->out_tail ^= 1;
1051 wake_up(&audio->write_wait);
1052 }
1053 }
1054
1055 if (audio->out_needed) {
1056 /* If the DSP currently wants data and we have a
1057 * buffer available, we will send it and reset
1058 * the needed flag. We'll mark the buffer as in-flight
1059 * so that it won't be recycled until the next buffer
1060 * is requested
1061 */
1062
1063 frame = audio->out + audio->out_tail;
1064 if (frame->used) {
1065 BUG_ON(frame->used == 0xffffffff);
1066 audrec_pcm_buffer_ptr_refresh(audio,
1067 audio->out_tail,
1068 frame->used);
1069 frame->used = 0xffffffff;
1070 audio->out_needed = 0;
1071 }
1072 }
1073 done:
1074 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1075}
1076
1077
Steve Mucklef132c6c2012-06-06 18:30:57 -07001078static int audaac_in_fsync(struct file *file, loff_t a, loff_t b, int datasync)
Manish Dewangan95ae3572011-03-15 14:58:12 +05301079
1080{
1081 struct audio_aac_in *audio = file->private_data;
1082 int rc = 0;
1083
1084 MM_DBG("\n"); /* Macro prints the file name and function */
1085 if (!audio->running || (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)) {
1086 rc = -EINVAL;
1087 goto done_nolock;
1088 }
1089
1090 mutex_lock(&audio->write_lock);
1091
1092 rc = wait_event_interruptible(audio->write_wait,
1093 audio->wflush);
1094 MM_DBG("waked on by some event audio->wflush = %d\n", audio->wflush);
1095
1096 if (rc < 0)
1097 goto done;
1098 else if (audio->wflush) {
1099 rc = -EBUSY;
1100 goto done;
1101 }
1102done:
1103 mutex_unlock(&audio->write_lock);
1104done_nolock:
1105 return rc;
1106
1107}
1108
1109int audrec_aac_process_eos(struct audio_aac_in *audio,
1110 const char __user *buf_start, unsigned short mfield_size)
1111{
1112 struct buffer *frame;
1113 int rc = 0;
1114
1115 frame = audio->out + audio->out_head;
1116
1117 rc = wait_event_interruptible(audio->write_wait,
1118 (audio->out_needed &&
1119 audio->out[0].used == 0 &&
1120 audio->out[1].used == 0)
1121 || (audio->stopped)
1122 || (audio->wflush));
1123
1124 if (rc < 0)
1125 goto done;
1126 if (audio->stopped || audio->wflush) {
1127 rc = -EBUSY;
1128 goto done;
1129 }
1130 if (copy_from_user(frame->data, buf_start, mfield_size)) {
1131 rc = -EFAULT;
1132 goto done;
1133 }
1134
1135 frame->mfield_sz = mfield_size;
1136 audio->out_head ^= 1;
1137 frame->used = mfield_size;
1138 MM_DBG("copying meta_out frame->used = %d\n", frame->used);
1139 audrec_pcm_send_data(audio, 0);
1140done:
1141 return rc;
1142}
1143static ssize_t audaac_in_write(struct file *file,
1144 const char __user *buf,
1145 size_t count, loff_t *pos)
1146{
1147 struct audio_aac_in *audio = file->private_data;
1148 const char __user *start = buf;
1149 struct buffer *frame;
1150 char *cpy_ptr;
1151 int rc = 0, eos_condition = AUDPREPROC_AAC_EOS_NONE;
1152 unsigned short mfield_size = 0;
1153 int write_count = 0;
1154 MM_DBG("cnt=%d\n", count);
1155
1156 if (count & 1)
1157 return -EINVAL;
1158
1159 if (audio->mode != MSM_AUD_ENC_MODE_NONTUNNEL)
1160 return -EINVAL;
1161
1162 mutex_lock(&audio->write_lock);
1163 frame = audio->out + audio->out_head;
1164 /* if supplied count is more than driver buffer size
1165 * then only copy driver buffer size
1166 */
1167 if (count > frame->size)
1168 count = frame->size;
1169
1170 write_count = count;
1171 cpy_ptr = frame->data;
1172 rc = wait_event_interruptible(audio->write_wait,
1173 (frame->used == 0)
1174 || (audio->stopped)
1175 || (audio->wflush));
1176 if (rc < 0)
1177 goto error;
1178
1179 if (audio->stopped || audio->wflush) {
1180 rc = -EBUSY;
1181 goto error;
1182 }
1183 if (audio->mfield) {
1184 if (buf == start) {
1185 /* Processing beginning of user buffer */
1186 if (__get_user(mfield_size,
1187 (unsigned short __user *) buf)) {
1188 rc = -EFAULT;
1189 goto error;
1190 } else if (mfield_size > count) {
1191 rc = -EINVAL;
1192 goto error;
1193 }
1194 MM_DBG("mf offset_val %x\n", mfield_size);
1195 if (copy_from_user(cpy_ptr, buf, mfield_size)) {
1196 rc = -EFAULT;
1197 goto error;
1198 }
1199 /* Check if EOS flag is set and buffer has
1200 * contains just meta field
1201 */
1202 if (cpy_ptr[AUDPREPROC_AAC_EOS_FLG_OFFSET] &
1203 AUDPREPROC_AAC_EOS_FLG_MASK) {
1204 eos_condition = AUDPREPROC_AAC_EOS_SET;
1205 MM_DBG("EOS SET\n");
1206 if (mfield_size == count) {
1207 buf += mfield_size;
1208 eos_condition = 0;
1209 goto exit;
1210 } else
1211 cpy_ptr[AUDPREPROC_AAC_EOS_FLG_OFFSET] &=
1212 ~AUDPREPROC_AAC_EOS_FLG_MASK;
1213 }
1214 cpy_ptr += mfield_size;
1215 count -= mfield_size;
1216 buf += mfield_size;
1217 } else {
1218 mfield_size = 0;
1219 MM_DBG("continuous buffer\n");
1220 }
1221 frame->mfield_sz = mfield_size;
1222 }
1223 MM_DBG("copying the stream count = %d\n", count);
1224 if (copy_from_user(cpy_ptr, buf, count)) {
1225 rc = -EFAULT;
1226 goto error;
1227 }
1228exit:
1229 frame->used = count;
1230 audio->out_head ^= 1;
1231 if (!audio->flush_ack)
1232 audrec_pcm_send_data(audio, 0);
1233 else {
1234 audrec_pcm_send_data(audio, 1);
1235 audio->flush_ack = 0;
1236 }
1237 if (eos_condition == AUDPREPROC_AAC_EOS_SET)
1238 rc = audrec_aac_process_eos(audio, start, mfield_size);
1239 mutex_unlock(&audio->write_lock);
1240 return write_count;
1241error:
1242 mutex_unlock(&audio->write_lock);
1243 return rc;
1244}
1245
1246static int audaac_in_release(struct inode *inode, struct file *file)
1247{
1248 struct audio_aac_in *audio = file->private_data;
1249
1250 mutex_lock(&audio->lock);
1251 audaac_in_disable(audio);
1252 audaac_in_flush(audio);
1253 msm_adsp_put(audio->audrec);
1254
Manish Dewangan95ae3572011-03-15 14:58:12 +05301255
1256 audpreproc_aenc_free(audio->enc_id);
1257 audio->audrec = NULL;
Manish Dewangan95ae3572011-03-15 14:58:12 +05301258 audio->opened = 0;
1259
1260 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
1261 (audio->out_data)) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301262 ion_unmap_kernel(audio->client, audio->input_buff_handle);
1263 ion_free(audio->client, audio->input_buff_handle);
Manish Dewangan95ae3572011-03-15 14:58:12 +05301264 audio->out_data = NULL;
1265 }
Santosh Mardi7faa0fa2011-09-22 15:32:23 +05301266
1267 if (audio->data) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301268 ion_unmap_kernel(audio->client, audio->output_buff_handle);
1269 ion_free(audio->client, audio->output_buff_handle);
Santosh Mardi7faa0fa2011-09-22 15:32:23 +05301270 audio->data = NULL;
1271 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301272 ion_client_destroy(audio->client);
Manish Dewangan95ae3572011-03-15 14:58:12 +05301273 mutex_unlock(&audio->lock);
1274 return 0;
1275}
1276
1277struct audio_aac_in the_audio_aac_in;
1278
1279static int audaac_in_open(struct inode *inode, struct file *file)
1280{
1281 struct audio_aac_in *audio = &the_audio_aac_in;
1282 int rc;
1283 int encid;
1284 int dma_size = 0;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301285 int len = 0;
1286 unsigned long ionflag = 0;
1287 ion_phys_addr_t addr = 0;
1288 struct ion_handle *handle = NULL;
1289 struct ion_client *client = NULL;
Manish Dewangan95ae3572011-03-15 14:58:12 +05301290
1291 mutex_lock(&audio->lock);
1292 if (audio->opened) {
1293 rc = -EBUSY;
1294 goto done;
1295 }
1296 if ((file->f_mode & FMODE_WRITE) &&
1297 (file->f_mode & FMODE_READ)) {
1298 audio->mode = MSM_AUD_ENC_MODE_NONTUNNEL;
1299 dma_size = NT_DMASZ;
1300 MM_DBG("Opened for non tunnel mode encoding\n");
1301 } else if (!(file->f_mode & FMODE_WRITE) &&
1302 (file->f_mode & FMODE_READ)) {
1303 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
1304 dma_size = DMASZ;
1305 MM_DBG("Opened for tunnel mode encoding\n");
1306 } else {
1307 MM_ERR("Invalid mode\n");
1308 rc = -EACCES;
1309 goto done;
1310 }
1311
1312 /* Settings will be re-config at AUDIO_SET_CONFIG,
1313 * but at least we need to have initial config
1314 */
1315 audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_11025;
1316 audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_11025;
1317
1318 /* For AAC, bit rate hard coded, default settings is
1319 * sample rate (11025) x channel count (1) x recording quality (1.75)
1320 * = 19293 bps */
1321 audio->bit_rate = 19293;
1322 audio->record_quality = 0x1c00;
1323
1324 audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
1325 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
1326 audio->buffer_size = (AAC_FRAME_SIZE + 14);
1327 else
1328 audio->buffer_size = (FRAME_SIZE - 8);
1329 audio->enc_type = AUDREC_CMD_TYPE_0_INDEX_AAC | audio->mode;
1330
1331 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
1332 rc = audmgr_open(&audio->audmgr);
1333 if (rc)
1334 goto done;
1335 }
1336
1337 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
1338 &audio->queue_ids);
1339 if (encid < 0) {
1340 MM_ERR("No free encoder available\n");
1341 rc = -ENODEV;
1342 goto done;
1343 }
1344 audio->enc_id = encid;
1345
1346 rc = msm_adsp_get(audio->module_name, &audio->audrec,
1347 &audrec_aac_adsp_ops, audio);
1348 if (rc) {
1349 audpreproc_aenc_free(audio->enc_id);
1350 goto done;
1351 }
1352
Manish Dewangan95ae3572011-03-15 14:58:12 +05301353 audio->dsp_cnt = 0;
1354 audio->stopped = 0;
1355 audio->wflush = 0;
1356 audio->rflush = 0;
1357 audio->flush_ack = 0;
1358
1359 audaac_in_flush(audio);
1360 audaac_out_flush(audio);
1361
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301362
1363 client = msm_ion_client_create(UINT_MAX, "Audio_AAC_in_client");
1364 if (IS_ERR_OR_NULL(client)) {
1365 MM_ERR("Unable to create ION client\n");
Manish Dewangan95ae3572011-03-15 14:58:12 +05301366 rc = -ENOMEM;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301367 goto client_create_error;
Manish Dewangan95ae3572011-03-15 14:58:12 +05301368 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301369 audio->client = client;
1370
1371 MM_DBG("allocating mem sz = %d\n", dma_size);
1372 handle = ion_alloc(client, dma_size, SZ_4K,
Hanumant Singh7d72bad2012-08-29 18:39:44 -07001373 ION_HEAP(ION_AUDIO_HEAP_ID), 0);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301374 if (IS_ERR_OR_NULL(handle)) {
1375 MM_ERR("Unable to create allocate O/P buffers\n");
1376 rc = -ENOMEM;
1377 goto output_buff_alloc_error;
1378 }
1379
1380 audio->output_buff_handle = handle;
1381
1382 rc = ion_phys(client , handle, &addr, &len);
1383 if (rc) {
1384 MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
1385 (unsigned int) addr, (unsigned int) len);
1386 rc = -ENOMEM;
1387 goto output_buff_get_phys_error;
1388 } else {
1389 MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
1390 (unsigned int) addr, (unsigned int) len);
1391 }
1392 audio->phys = (int32_t)addr;
1393
1394 rc = ion_handle_get_flags(client, handle, &ionflag);
1395 if (rc) {
1396 MM_ERR("could not get flags for the handle\n");
1397 rc = -ENOMEM;
1398 goto output_buff_get_flags_error;
1399 }
1400
Mitchel Humpherys911b4b72012-09-12 14:42:50 -07001401 audio->map_v_read = ion_map_kernel(client, handle);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301402 if (IS_ERR(audio->map_v_read)) {
1403 MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
1404 (int)audio);
1405 rc = -ENOMEM;
1406 goto output_buff_map_error;
1407 }
1408 audio->data = audio->map_v_read;
1409 MM_DBG("read buf: phy addr 0x%08x kernel addr 0x%08x\n",
1410 audio->phys, (int)audio->data);
Manish Dewangan95ae3572011-03-15 14:58:12 +05301411
1412 audio->out_data = NULL;
1413 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301414
1415 MM_DBG("allocating BUFFER_SIZE %d\n", BUFFER_SIZE);
1416 handle = ion_alloc(client, BUFFER_SIZE,
Hanumant Singh7d72bad2012-08-29 18:39:44 -07001417 SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301418 if (IS_ERR_OR_NULL(handle)) {
1419 MM_ERR("Unable to create allocate I/P buffers\n");
Manish Dewangan95ae3572011-03-15 14:58:12 +05301420 rc = -ENOMEM;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301421 goto input_buff_alloc_error;
Manish Dewangan95ae3572011-03-15 14:58:12 +05301422 }
1423
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301424 audio->input_buff_handle = handle;
1425
1426 rc = ion_phys(client , handle, &addr, &len);
1427 if (rc) {
1428 MM_ERR("I/P buffers:Invalid phy: %x sz: %x\n",
1429 (unsigned int) addr, (unsigned int) len);
1430 rc = -ENOMEM;
1431 goto input_buff_get_phys_error;
1432 } else {
1433 MM_INFO("Got valid phy: %x sz: %x\n",
1434 (unsigned int) addr,
1435 (unsigned int) len);
1436 }
1437 audio->out_phys = (int32_t)addr;
1438
1439 rc = ion_handle_get_flags(client,
1440 handle, &ionflag);
1441 if (rc) {
1442 MM_ERR("could not get flags for the handle\n");
1443 rc = -ENOMEM;
1444 goto input_buff_get_flags_error;
1445 }
1446
Mitchel Humpherys911b4b72012-09-12 14:42:50 -07001447 audio->map_v_write = ion_map_kernel(client, handle);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301448 if (IS_ERR(audio->map_v_write)) {
1449 MM_ERR("could not map write buffers\n");
1450 rc = -ENOMEM;
1451 goto input_buff_map_error;
1452 }
1453 audio->out_data = audio->map_v_write;
1454 MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
1455 (unsigned int)addr,
1456 (unsigned int)audio->out_data);
1457
Manish Dewangan95ae3572011-03-15 14:58:12 +05301458 /* Initialize buffer */
1459 audio->out[0].data = audio->out_data + 0;
1460 audio->out[0].addr = audio->out_phys + 0;
1461 audio->out[0].size = OUT_BUFFER_SIZE;
1462
1463 audio->out[1].data = audio->out_data + OUT_BUFFER_SIZE;
1464 audio->out[1].addr = audio->out_phys + OUT_BUFFER_SIZE;
1465 audio->out[1].size = OUT_BUFFER_SIZE;
1466
1467 MM_DBG("audio->out[0].data = %d audio->out[1].data = %d",
1468 (unsigned int)audio->out[0].data,
1469 (unsigned int)audio->out[1].data);
1470 audio->mfield = NT_FRAME_HEADER_SIZE;
1471 audio->out_frame_cnt++;
1472 }
1473 file->private_data = audio;
1474 audio->opened = 1;
1475
1476done:
1477 mutex_unlock(&audio->lock);
1478 return rc;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301479input_buff_map_error:
1480input_buff_get_flags_error:
1481input_buff_get_phys_error:
1482 ion_free(client, audio->input_buff_handle);
1483input_buff_alloc_error:
1484 ion_unmap_kernel(client, audio->output_buff_handle);
1485output_buff_map_error:
1486output_buff_get_phys_error:
1487output_buff_get_flags_error:
1488 ion_free(client, audio->output_buff_handle);
1489output_buff_alloc_error:
1490 ion_client_destroy(client);
1491client_create_error:
Manish Dewangan95ae3572011-03-15 14:58:12 +05301492 msm_adsp_put(audio->audrec);
Manish Dewangan95ae3572011-03-15 14:58:12 +05301493
1494 audpreproc_aenc_free(audio->enc_id);
1495 mutex_unlock(&audio->lock);
1496 return rc;
1497}
1498
1499static const struct file_operations audio_aac_in_fops = {
1500 .owner = THIS_MODULE,
1501 .open = audaac_in_open,
1502 .release = audaac_in_release,
1503 .read = audaac_in_read,
1504 .write = audaac_in_write,
1505 .fsync = audaac_in_fsync,
1506 .unlocked_ioctl = audaac_in_ioctl,
1507};
1508
1509static struct miscdevice audaac_in_misc = {
1510 .minor = MISC_DYNAMIC_MINOR,
1511 .name = "msm_aac_in",
1512 .fops = &audio_aac_in_fops,
1513};
1514
1515static int __init audaac_in_init(void)
1516{
1517 mutex_init(&the_audio_aac_in.lock);
1518 mutex_init(&the_audio_aac_in.read_lock);
1519 spin_lock_init(&the_audio_aac_in.dsp_lock);
1520 init_waitqueue_head(&the_audio_aac_in.wait);
1521 init_waitqueue_head(&the_audio_aac_in.wait_enable);
1522 mutex_init(&the_audio_aac_in.write_lock);
1523 init_waitqueue_head(&the_audio_aac_in.write_wait);
1524 return misc_register(&audaac_in_misc);
1525}
1526device_initcall(audaac_in_init);