blob: 7f68c03232ad16e0381a06070cef606ec5d70416 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * pcm audio input device
3 *
4 * Copyright (C) 2008 Google, Inc.
5 * Copyright (C) 2008 HTC Corporation
6 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
Santosh Mardifdc227a2011-07-11 17:20:34 +053019#include <asm/atomic.h>
20#include <asm/ioctls.h>
21
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070022#include <linux/module.h>
23#include <linux/fs.h>
24#include <linux/miscdevice.h>
25#include <linux/uaccess.h>
26#include <linux/sched.h>
27#include <linux/wait.h>
28#include <linux/dma-mapping.h>
29#include <linux/msm_audio.h>
30#include <linux/android_pmem.h>
Santosh Mardifdc227a2011-07-11 17:20:34 +053031#include <linux/memory_alloc.h>
32#include <mach/msm_memtypes.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070033
Santosh Mardifdc227a2011-07-11 17:20:34 +053034#include <mach/iommu.h>
35#include <mach/iommu_domains.h>
36#include <mach/msm_subsystem_map.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070037
38#include <mach/msm_adsp.h>
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +053039#include <mach/socinfo.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040#include <mach/qdsp5v2/qdsp5audreccmdi.h>
41#include <mach/qdsp5v2/qdsp5audrecmsg.h>
42#include <mach/qdsp5v2/audpreproc.h>
43#include <mach/qdsp5v2/audio_dev_ctl.h>
44#include <mach/debug_mm.h>
45#include <mach/qdsp5v2/audio_acdbi.h>
46
47/* FRAME_NUM must be a power of two */
48#define FRAME_NUM (8)
49#define FRAME_HEADER_SIZE (8) /*4 half words*/
50/* size of a mono frame with 256 samples */
51#define MONO_DATA_SIZE_256 (512) /* in bytes*/
52/*size of a mono frame with 512 samples */
53#define MONO_DATA_SIZE_512 (1024) /* in bytes*/
54/*size of a mono frame with 1024 samples */
55#define MONO_DATA_SIZE_1024 (2048) /* in bytes */
56
57/*size of a stereo frame with 256 samples per channel */
58#define STEREO_DATA_SIZE_256 (1024) /* in bytes*/
59/*size of a stereo frame with 512 samples per channel */
60#define STEREO_DATA_SIZE_512 (2048) /* in bytes*/
61/*size of a stereo frame with 1024 samples per channel */
62#define STEREO_DATA_SIZE_1024 (4096) /* in bytes */
63
64#define MAX_FRAME_SIZE ((STEREO_DATA_SIZE_1024) + FRAME_HEADER_SIZE)
65#define DMASZ (MAX_FRAME_SIZE * FRAME_NUM)
66
67struct buffer {
68 void *data;
69 uint32_t size;
70 uint32_t read;
71 uint32_t addr;
72};
73
74struct audio_in {
75 struct buffer in[FRAME_NUM];
76
77 spinlock_t dsp_lock;
78
79 atomic_t in_bytes;
80 atomic_t in_samples;
81
82 struct mutex lock;
83 struct mutex read_lock;
84 wait_queue_head_t wait;
85 wait_queue_head_t wait_enable;
86
87 struct msm_adsp_module *audrec;
88
89 /* configuration to use on next enable */
90 uint32_t samp_rate;
91 uint32_t channel_mode;
92 uint32_t buffer_size; /* 2048 for mono, 4096 for stereo */
93 uint32_t enc_type;
94
95 uint32_t dsp_cnt;
96 uint32_t in_head; /* next buffer dsp will write */
97 uint32_t in_tail; /* next buffer read() will read */
98 uint32_t in_count; /* number of buffers available to read() */
99 uint32_t mode;
100
101 const char *module_name;
102 unsigned queue_ids;
103 uint16_t enc_id; /* Session Id */
104
105 uint16_t source; /* Encoding source bit mask */
106 uint32_t device_events; /* device events interested in */
107 uint32_t in_call;
108 uint32_t dev_cnt;
109 int voice_state;
110 spinlock_t dev_lock;
111
112 struct audrec_session_info session_info; /*audrec session info*/
113 /* data allocated for various buffers */
114 char *data;
115 dma_addr_t phys;
Santosh Mardifdc227a2011-07-11 17:20:34 +0530116 struct msm_mapped_buffer *map_v_read;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117
118 int opened;
119 int enabled;
120 int running;
121 int stopped; /* set when stopped, cleared on flush */
122 int abort; /* set when error, like sample rate mismatch */
123 int dual_mic_config;
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +0530124 char *build_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700125};
126
127static struct audio_in the_audio_in;
128
129struct audio_frame {
130 uint16_t frame_count_lsw;
131 uint16_t frame_count_msw;
132 uint16_t frame_length;
133 uint16_t erased_pcm;
134 unsigned char raw_bitstream[]; /* samples */
135} __attribute__((packed));
136
137/* Audrec Queue command sent macro's */
138#define audrec_send_bitstreamqueue(audio, cmd, len) \
139 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
140 cmd, len)
141
142#define audrec_send_audrecqueue(audio, cmd, len) \
143 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
144 cmd, len)
145
146/* DSP command send functions */
147static int audpcm_in_enc_config(struct audio_in *audio, int enable);
148static int audpcm_in_param_config(struct audio_in *audio);
149static int audpcm_in_mem_config(struct audio_in *audio);
150static int audpcm_in_record_config(struct audio_in *audio, int enable);
151static int audpcm_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt);
152
153static void audpcm_in_get_dsp_frames(struct audio_in *audio);
154
155static void audpcm_in_flush(struct audio_in *audio);
156
157static void pcm_in_listener(u32 evt_id, union auddev_evt_data *evt_payload,
158 void *private_data)
159{
160 struct audio_in *audio = (struct audio_in *) private_data;
161 unsigned long flags;
162
163 MM_DBG("evt_id = 0x%8x\n", evt_id);
164 switch (evt_id) {
165 case AUDDEV_EVT_DEV_RDY: {
166 MM_DBG("AUDDEV_EVT_DEV_RDY\n");
167 spin_lock_irqsave(&audio->dev_lock, flags);
168 audio->dev_cnt++;
169 if (!audio->in_call)
170 audio->source |= (0x1 << evt_payload->routing_id);
171 spin_unlock_irqrestore(&audio->dev_lock, flags);
172
173 if ((audio->running == 1) && (audio->enabled == 1))
174 audpcm_in_record_config(audio, 1);
175
176 break;
177 }
178 case AUDDEV_EVT_DEV_RLS: {
179 MM_DBG("AUDDEV_EVT_DEV_RLS\n");
180 spin_lock_irqsave(&audio->dev_lock, flags);
181 audio->dev_cnt--;
182 if (!audio->in_call)
183 audio->source &= ~(0x1 << evt_payload->routing_id);
184 spin_unlock_irqrestore(&audio->dev_lock, flags);
185
186 if (!audio->running || !audio->enabled)
187 break;
188
189 /* Turn of as per source */
190 if (audio->source)
191 audpcm_in_record_config(audio, 1);
192 else
193 /* Turn off all */
194 audpcm_in_record_config(audio, 0);
195
196 break;
197 }
198 case AUDDEV_EVT_VOICE_STATE_CHG: {
199 MM_DBG("AUDDEV_EVT_VOICE_STATE_CHG, state = %d\n",
200 evt_payload->voice_state);
201 audio->voice_state = evt_payload->voice_state;
202 if (audio->in_call && audio->running) {
203 if (audio->voice_state == VOICE_STATE_INCALL)
204 audpcm_in_record_config(audio, 1);
205 else if (audio->voice_state == VOICE_STATE_OFFCALL) {
206 audpcm_in_record_config(audio, 0);
207 wake_up(&audio->wait);
208 }
209 }
210 break;
211 }
212 case AUDDEV_EVT_FREQ_CHG: {
213 MM_DBG("Encoder Driver got sample rate change event\n");
214 MM_DBG("sample rate %d\n", evt_payload->freq_info.sample_rate);
215 MM_DBG("dev_type %d\n", evt_payload->freq_info.dev_type);
216 MM_DBG("acdb_dev_id %d\n", evt_payload->freq_info.acdb_dev_id);
217 if (audio->running == 1) {
218 /* Stop Recording sample rate does not match
219 with device sample rate */
220 if (evt_payload->freq_info.sample_rate !=
221 audio->samp_rate) {
222 audpcm_in_record_config(audio, 0);
223 audio->abort = 1;
224 wake_up(&audio->wait);
225 }
226 }
227 break;
228 }
229 default:
230 MM_ERR("wrong event %d\n", evt_id);
231 break;
232 }
233}
234
235/* ------------------- dsp preproc event handler--------------------- */
236static void audpreproc_dsp_event(void *data, unsigned id, void *msg)
237{
238 struct audio_in *audio = data;
239
240 switch (id) {
241 case AUDPREPROC_ERROR_MSG: {
242 struct audpreproc_err_msg *err_msg = msg;
243
244 MM_ERR("ERROR_MSG: stream id %d err idx %d\n",
245 err_msg->stream_id, err_msg->aud_preproc_err_idx);
246 /* Error case */
247 wake_up(&audio->wait_enable);
248 break;
249 }
250 case AUDPREPROC_CMD_CFG_DONE_MSG: {
251 MM_DBG("CMD_CFG_DONE_MSG \n");
252 break;
253 }
254 case AUDPREPROC_CMD_ENC_CFG_DONE_MSG: {
255 struct audpreproc_cmd_enc_cfg_done_msg *enc_cfg_msg = msg;
256
257 MM_DBG("CMD_ENC_CFG_DONE_MSG: stream id %d enc type \
258 0x%8x\n", enc_cfg_msg->stream_id,
259 enc_cfg_msg->rec_enc_type);
260 /* Encoder enable success */
261 if (enc_cfg_msg->rec_enc_type & ENCODE_ENABLE)
262 audpcm_in_param_config(audio);
263 else { /* Encoder disable success */
264 audio->running = 0;
265 audpcm_in_record_config(audio, 0);
266 }
267 break;
268 }
269 case AUDPREPROC_CMD_ENC_PARAM_CFG_DONE_MSG: {
270 MM_DBG("CMD_ENC_PARAM_CFG_DONE_MSG \n");
271 audpcm_in_mem_config(audio);
272 break;
273 }
274 case AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG: {
275 MM_DBG("AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG \n");
276 wake_up(&audio->wait_enable);
277 break;
278 }
279 default:
280 MM_ERR("Unknown Event id %d\n", id);
281 }
282}
283
284/* ------------------- dsp audrec event handler--------------------- */
285static void audrec_dsp_event(void *data, unsigned id, size_t len,
286 void (*getevent)(void *ptr, size_t len))
287{
288 struct audio_in *audio = data;
289
290 switch (id) {
291 case AUDREC_CMD_MEM_CFG_DONE_MSG: {
292 MM_DBG("CMD_MEM_CFG_DONE MSG DONE\n");
293 audio->running = 1;
294 if ((!audio->in_call && (audio->dev_cnt > 0)) ||
295 (audio->in_call &&
296 (audio->voice_state == VOICE_STATE_INCALL)))
297 audpcm_in_record_config(audio, 1);
298 break;
299 }
300 case AUDREC_FATAL_ERR_MSG: {
301 struct audrec_fatal_err_msg fatal_err_msg;
302
303 getevent(&fatal_err_msg, AUDREC_FATAL_ERR_MSG_LEN);
304 MM_ERR("FATAL_ERR_MSG: err id %d\n",
305 fatal_err_msg.audrec_err_id);
306 /* Error stop the encoder */
307 audio->stopped = 1;
308 wake_up(&audio->wait);
309 break;
310 }
311 case AUDREC_UP_PACKET_READY_MSG: {
312 struct audrec_up_pkt_ready_msg pkt_ready_msg;
313
314 getevent(&pkt_ready_msg, AUDREC_UP_PACKET_READY_MSG_LEN);
315 MM_DBG("UP_PACKET_READY_MSG: write cnt lsw %d \
316 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
317 pkt_ready_msg.audrec_packet_write_cnt_lsw, \
318 pkt_ready_msg.audrec_packet_write_cnt_msw, \
319 pkt_ready_msg.audrec_up_prev_read_cnt_lsw, \
320 pkt_ready_msg.audrec_up_prev_read_cnt_msw);
321
322 audpcm_in_get_dsp_frames(audio);
323 break;
324 }
325 case ADSP_MESSAGE_ID: {
326 MM_DBG("Received ADSP event :module audrectask\n");
327 break;
328 }
329 default:
330 MM_ERR("Unknown Event id %d\n", id);
331 }
332}
333
334static void audpcm_in_get_dsp_frames(struct audio_in *audio)
335{
336 struct audio_frame *frame;
337 uint32_t index;
338 unsigned long flags;
339
340 index = audio->in_head;
341
342 frame = (void *) (((char *)audio->in[index].data) - \
343 sizeof(*frame));
344
345 spin_lock_irqsave(&audio->dsp_lock, flags);
346 audio->in[index].size = frame->frame_length;
347
348 /* statistics of read */
349 atomic_add(audio->in[index].size, &audio->in_bytes);
350 atomic_add(1, &audio->in_samples);
351
352 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
353
354 /* If overflow, move the tail index foward. */
355 if (audio->in_head == audio->in_tail)
356 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
357 else
358 audio->in_count++;
359
360 audpcm_dsp_read_buffer(audio, audio->dsp_cnt++);
361 spin_unlock_irqrestore(&audio->dsp_lock, flags);
362
363 wake_up(&audio->wait);
364}
365
366struct msm_adsp_ops audrec_adsp_ops = {
367 .event = audrec_dsp_event,
368};
369
370static int audpcm_in_enc_config(struct audio_in *audio, int enable)
371{
372 struct audpreproc_audrec_cmd_enc_cfg cmd;
373
374 memset(&cmd, 0, sizeof(cmd));
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +0530375 if (audio->build_id[17] == '1') {
376 cmd.cmd_id = AUDPREPROC_AUDREC_CMD_ENC_CFG_2;
377 MM_ERR("sending AUDPREPROC_AUDREC_CMD_ENC_CFG_2 command");
378 } else {
379 cmd.cmd_id = AUDPREPROC_AUDREC_CMD_ENC_CFG;
380 MM_ERR("sending AUDPREPROC_AUDREC_CMD_ENC_CFG command");
381 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700382 cmd.stream_id = audio->enc_id;
383
384 if (enable)
385 cmd.audrec_enc_type = audio->enc_type | ENCODE_ENABLE;
386 else
387 cmd.audrec_enc_type &= ~(ENCODE_ENABLE);
388
389 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
390}
391
392static int audpcm_in_param_config(struct audio_in *audio)
393{
394 struct audpreproc_audrec_cmd_parm_cfg_wav cmd;
395
396 memset(&cmd, 0, sizeof(cmd));
397 cmd.common.cmd_id = AUDPREPROC_AUDREC_CMD_PARAM_CFG;
398 cmd.common.stream_id = audio->enc_id;
399
400 cmd.aud_rec_samplerate_idx = audio->samp_rate;
401 if (audio->dual_mic_config)
402 cmd.aud_rec_stereo_mode = DUAL_MIC_STEREO_RECORDING;
403 else
404 cmd.aud_rec_stereo_mode = audio->channel_mode;
405
406 if (audio->channel_mode == AUDREC_CMD_MODE_MONO)
407 cmd.aud_rec_frame_size = audio->buffer_size/2;
408 else
409 cmd.aud_rec_frame_size = audio->buffer_size/4;
410 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
411}
412
413/* To Do: msm_snddev_route_enc(audio->enc_id); */
414static int audpcm_in_record_config(struct audio_in *audio, int enable)
415{
416 struct audpreproc_afe_cmd_audio_record_cfg cmd;
417
418 memset(&cmd, 0, sizeof(cmd));
419 cmd.cmd_id = AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG;
420 cmd.stream_id = audio->enc_id;
421 if (enable)
422 cmd.destination_activity = AUDIO_RECORDING_TURN_ON;
423 else
424 cmd.destination_activity = AUDIO_RECORDING_TURN_OFF;
425
426 cmd.source_mix_mask = audio->source;
427 if (audio->enc_id == 2) {
428 if ((cmd.source_mix_mask &
429 INTERNAL_CODEC_TX_SOURCE_MIX_MASK) ||
430 (cmd.source_mix_mask & AUX_CODEC_TX_SOURCE_MIX_MASK) ||
431 (cmd.source_mix_mask & VOICE_UL_SOURCE_MIX_MASK) ||
432 (cmd.source_mix_mask & VOICE_DL_SOURCE_MIX_MASK)) {
433 cmd.pipe_id = SOURCE_PIPE_1;
434 }
435 if (cmd.source_mix_mask &
436 AUDPP_A2DP_PIPE_SOURCE_MIX_MASK)
437 cmd.pipe_id |= SOURCE_PIPE_0;
438 }
439
440 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
441}
442
443static int audpcm_in_mem_config(struct audio_in *audio)
444{
445 struct audrec_cmd_arecmem_cfg cmd;
446 uint16_t *data = (void *) audio->data;
447 int n;
448
449 memset(&cmd, 0, sizeof(cmd));
450 cmd.cmd_id = AUDREC_CMD_MEM_CFG_CMD;
451 cmd.audrec_up_pkt_intm_count = 1;
452 cmd.audrec_ext_pkt_start_addr_msw = audio->phys >> 16;
453 cmd.audrec_ext_pkt_start_addr_lsw = audio->phys;
454 cmd.audrec_ext_pkt_buf_number = FRAME_NUM;
455
456 /* prepare buffer pointers:
457 * Mono: 1024 samples + 4 halfword header
458 * Stereo: 2048 samples + 4 halfword header
459 */
460 for (n = 0; n < FRAME_NUM; n++) {
461 /* word increment*/
462 audio->in[n].data = data + (FRAME_HEADER_SIZE/2);
463 data += ((FRAME_HEADER_SIZE/2) + (audio->buffer_size/2));
464 MM_DBG("0x%8x\n", (int)(audio->in[n].data - FRAME_HEADER_SIZE));
465 }
466
467 return audrec_send_audrecqueue(audio, &cmd, sizeof(cmd));
468}
469
470static int audpcm_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt)
471{
472 struct up_audrec_packet_ext_ptr cmd;
473
474 memset(&cmd, 0, sizeof(cmd));
475 cmd.cmd_id = UP_AUDREC_PACKET_EXT_PTR;
476 cmd.audrec_up_curr_read_count_msw = read_cnt >> 16;
477 cmd.audrec_up_curr_read_count_lsw = read_cnt;
478
479 return audrec_send_bitstreamqueue(audio, &cmd, sizeof(cmd));
480}
481
482/* must be called with audio->lock held */
483static int audpcm_in_enable(struct audio_in *audio)
484{
485 if (audio->enabled)
486 return 0;
487
488 if (audpreproc_enable(audio->enc_id, &audpreproc_dsp_event, audio)) {
489 MM_ERR("msm_adsp_enable(audpreproc) failed\n");
490 return -ENODEV;
491 }
492
493 if (msm_adsp_enable(audio->audrec)) {
494 MM_ERR("msm_adsp_enable(audrec) failed\n");
495 audpreproc_disable(audio->enc_id, audio);
496 return -ENODEV;
497 }
498 audio->enabled = 1;
499 audpcm_in_enc_config(audio, 1);
500
501 return 0;
502}
503
504/* must be called with audio->lock held */
505static int audpcm_in_disable(struct audio_in *audio)
506{
507 if (audio->enabled) {
508 audio->enabled = 0;
509 audpcm_in_enc_config(audio, 0);
510 wake_up(&audio->wait);
511 wait_event_interruptible_timeout(audio->wait_enable,
512 audio->running == 0, 1*HZ);
513 msm_adsp_disable(audio->audrec);
514 audpreproc_disable(audio->enc_id, audio);
515 }
516 return 0;
517}
518
519static void audpcm_in_flush(struct audio_in *audio)
520{
521 int i;
522
523 audio->dsp_cnt = 0;
524 audio->in_head = 0;
525 audio->in_tail = 0;
526 audio->in_count = 0;
527 for (i = 0; i < FRAME_NUM; i++) {
528 audio->in[i].size = 0;
529 audio->in[i].read = 0;
530 }
531 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
532 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
533 atomic_set(&audio->in_bytes, 0);
534 atomic_set(&audio->in_samples, 0);
535}
536
537/* ------------------- device --------------------- */
538static long audpcm_in_ioctl(struct file *file,
539 unsigned int cmd, unsigned long arg)
540{
541 struct audio_in *audio = file->private_data;
542 int rc = 0;
543
544 if (cmd == AUDIO_GET_STATS) {
545 struct msm_audio_stats stats;
546 stats.byte_count = atomic_read(&audio->in_bytes);
547 stats.sample_count = atomic_read(&audio->in_samples);
548 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
549 return -EFAULT;
550 return rc;
551 }
552
553 mutex_lock(&audio->lock);
554 switch (cmd) {
555 case AUDIO_START: {
556 uint32_t freq;
557 /* Poll at 48KHz always */
558 freq = 48000;
559 MM_DBG("AUDIO_START\n");
560 if (audio->in_call && (audio->voice_state !=
561 VOICE_STATE_INCALL)) {
562 rc = -EPERM;
563 break;
564 }
565 rc = msm_snddev_request_freq(&freq, audio->enc_id,
566 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
567 MM_DBG("sample rate configured %d sample rate requested %d\n",
568 freq, audio->samp_rate);
569 if (rc < 0) {
570 MM_DBG("sample rate can not be set, return code %d\n",\
571 rc);
572 msm_snddev_withdraw_freq(audio->enc_id,
573 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
574 MM_DBG("msm_snddev_withdraw_freq\n");
575 break;
576 }
577 audio->dual_mic_config = msm_get_dual_mic_config(audio->enc_id);
578 /*DSP supports fluence block and by default ACDB layer will
579 applies the fluence pre-processing feature, if dual MIC config
580 is enabled implies client want to record pure dual MIC sample
581 for this we need to over ride the fluence pre processing
582 feature at ACDB layer to not to apply if fluence preprocessing
583 feature supported*/
584 if (audio->dual_mic_config) {
585 MM_INFO("dual MIC config = %d, over ride the fluence "
586 "feature\n", audio->dual_mic_config);
587 fluence_feature_update(audio->dual_mic_config,
588 audio->enc_id);
589 }
590 /*update aurec session info in audpreproc layer*/
591 audio->session_info.session_id = audio->enc_id;
592 audio->session_info.sampling_freq = audio->samp_rate;
593 audpreproc_update_audrec_info(&audio->session_info);
594 rc = audpcm_in_enable(audio);
595 if (!rc) {
596 rc =
597 wait_event_interruptible_timeout(audio->wait_enable,
598 audio->running != 0, 1*HZ);
599 MM_DBG("state %d rc = %d\n", audio->running, rc);
600
601 if (audio->running == 0)
602 rc = -ENODEV;
603 else
604 rc = 0;
605 }
606 audio->stopped = 0;
607 break;
608 }
609 case AUDIO_STOP: {
610 /*reset the sampling frequency information at audpreproc layer*/
611 audio->session_info.sampling_freq = 0;
612 audpreproc_update_audrec_info(&audio->session_info);
613 rc = audpcm_in_disable(audio);
614 rc = msm_snddev_withdraw_freq(audio->enc_id,
615 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
616 MM_DBG("msm_snddev_withdraw_freq\n");
617 audio->stopped = 1;
618 audio->abort = 0;
619 break;
620 }
621 case AUDIO_FLUSH: {
622 if (audio->stopped) {
623 /* Make sure we're stopped and we wake any threads
624 * that might be blocked holding the read_lock.
625 * While audio->stopped read threads will always
626 * exit immediately.
627 */
628 wake_up(&audio->wait);
629 mutex_lock(&audio->read_lock);
630 audpcm_in_flush(audio);
631 mutex_unlock(&audio->read_lock);
632 }
633 break;
634 }
635 case AUDIO_SET_CONFIG: {
636 struct msm_audio_config cfg;
637 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
638 rc = -EFAULT;
639 break;
640 }
641 if (cfg.channel_count == 1) {
642 cfg.channel_count = AUDREC_CMD_MODE_MONO;
643 if ((cfg.buffer_size == MONO_DATA_SIZE_256) ||
644 (cfg.buffer_size == MONO_DATA_SIZE_512) ||
645 (cfg.buffer_size == MONO_DATA_SIZE_1024)) {
646 audio->buffer_size = cfg.buffer_size;
647 } else {
648 rc = -EINVAL;
649 break;
650 }
651 } else if (cfg.channel_count == 2) {
652 cfg.channel_count = AUDREC_CMD_MODE_STEREO;
653 if ((cfg.buffer_size == STEREO_DATA_SIZE_256) ||
654 (cfg.buffer_size == STEREO_DATA_SIZE_512) ||
655 (cfg.buffer_size == STEREO_DATA_SIZE_1024)) {
656 audio->buffer_size = cfg.buffer_size;
657 } else {
658 rc = -EINVAL;
659 break;
660 }
661 } else {
662 rc = -EINVAL;
663 break;
664 }
665 audio->samp_rate = cfg.sample_rate;
666 audio->channel_mode = cfg.channel_count;
667 break;
668 }
669 case AUDIO_GET_CONFIG: {
670 struct msm_audio_config cfg;
671 memset(&cfg, 0, sizeof(cfg));
672 cfg.buffer_size = audio->buffer_size;
673 cfg.buffer_count = FRAME_NUM;
674 cfg.sample_rate = audio->samp_rate;
675 if (audio->channel_mode == AUDREC_CMD_MODE_MONO)
676 cfg.channel_count = 1;
677 else
678 cfg.channel_count = 2;
679 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
680 rc = -EFAULT;
681 break;
682 }
683 case AUDIO_SET_INCALL: {
684 struct msm_voicerec_mode cfg;
685 unsigned long flags;
686 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
687 rc = -EFAULT;
688 break;
689 }
690 if (cfg.rec_mode != VOC_REC_BOTH &&
691 cfg.rec_mode != VOC_REC_UPLINK &&
692 cfg.rec_mode != VOC_REC_DOWNLINK) {
693 MM_ERR("invalid rec_mode\n");
694 rc = -EINVAL;
695 break;
696 } else {
697 spin_lock_irqsave(&audio->dev_lock, flags);
698 if (cfg.rec_mode == VOC_REC_UPLINK)
699 audio->source = VOICE_UL_SOURCE_MIX_MASK;
700 else if (cfg.rec_mode == VOC_REC_DOWNLINK)
701 audio->source = VOICE_DL_SOURCE_MIX_MASK;
702 else
703 audio->source = VOICE_DL_SOURCE_MIX_MASK |
704 VOICE_UL_SOURCE_MIX_MASK ;
705 audio->in_call = 1;
706 spin_unlock_irqrestore(&audio->dev_lock, flags);
707 }
708 break;
709 }
710 case AUDIO_GET_SESSION_ID: {
711 if (copy_to_user((void *) arg, &audio->enc_id,
712 sizeof(unsigned short))) {
713 rc = -EFAULT;
714 }
715 break;
716 }
717 default:
718 rc = -EINVAL;
719 }
720 mutex_unlock(&audio->lock);
721 return rc;
722}
723
724static ssize_t audpcm_in_read(struct file *file,
725 char __user *buf,
726 size_t count, loff_t *pos)
727{
728 struct audio_in *audio = file->private_data;
729 unsigned long flags;
730 const char __user *start = buf;
731 void *data;
732 uint32_t index;
733 uint32_t size;
734 int rc = 0;
735
736 mutex_lock(&audio->read_lock);
737 while (count > 0) {
738 rc = wait_event_interruptible(
739 audio->wait, (audio->in_count > 0) || audio->stopped ||
740 audio->abort || (audio->in_call && audio->running &&
741 (audio->voice_state == VOICE_STATE_OFFCALL)));
742 if (rc < 0)
743 break;
744
745 if (!audio->in_count) {
746 if (audio->stopped) {
747 MM_DBG("Driver in stop state, No more \
748 buffer to read");
749 rc = 0;/* End of File */
750 break;
751 } else if (audio->in_call && audio->running &&
752 (audio->voice_state == VOICE_STATE_OFFCALL)) {
753 MM_DBG("Not Permitted Voice Terminated\n");
754 rc = -EPERM; /* Voice Call stopped */
755 break;
756 }
757 }
758
759 if (audio->abort) {
760 rc = -EPERM; /* Not permitted due to abort */
761 break;
762 }
763
764 index = audio->in_tail;
765 data = (uint8_t *) audio->in[index].data;
766 size = audio->in[index].size;
767 if (count >= size) {
768 if (copy_to_user(buf, data, size)) {
769 rc = -EFAULT;
770 break;
771 }
772 spin_lock_irqsave(&audio->dsp_lock, flags);
773 if (index != audio->in_tail) {
774 /* overrun -- data is
775 * invalid and we need to retry */
776 spin_unlock_irqrestore(&audio->dsp_lock, flags);
777 continue;
778 }
779 audio->in[index].size = 0;
780 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
781 audio->in_count--;
782 spin_unlock_irqrestore(&audio->dsp_lock, flags);
783 count -= size;
784 buf += size;
785 } else {
786 MM_ERR("short read count %d\n", count);
787 break;
788 }
789 }
790 mutex_unlock(&audio->read_lock);
791
792 if (buf > start)
793 return buf - start;
794
795 return rc;
796}
797
798static ssize_t audpcm_in_write(struct file *file,
799 const char __user *buf,
800 size_t count, loff_t *pos)
801{
802 return -EINVAL;
803}
804
805static int audpcm_in_release(struct inode *inode, struct file *file)
806{
807 struct audio_in *audio = file->private_data;
808
809 mutex_lock(&audio->lock);
810 audio->in_call = 0;
811 /* with draw frequency for session
812 incase not stopped the driver */
813 msm_snddev_withdraw_freq(audio->enc_id, SNDDEV_CAP_TX,
814 AUDDEV_CLNT_ENC);
815 auddev_unregister_evt_listner(AUDDEV_CLNT_ENC, audio->enc_id);
816 /*reset the sampling frequency information at audpreproc layer*/
817 audio->session_info.sampling_freq = 0;
818 audpreproc_update_audrec_info(&audio->session_info);
819 audpcm_in_disable(audio);
820 audpcm_in_flush(audio);
821 msm_adsp_put(audio->audrec);
822 audpreproc_aenc_free(audio->enc_id);
823 audio->audrec = NULL;
824 audio->opened = 0;
825 if (audio->data) {
Santosh Mardifdc227a2011-07-11 17:20:34 +0530826 msm_subsystem_unmap_buffer(audio->map_v_read);
827 free_contiguous_memory_by_paddr(audio->phys);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700828 audio->data = NULL;
829 }
830 mutex_unlock(&audio->lock);
831 return 0;
832}
833
834static int audpcm_in_open(struct inode *inode, struct file *file)
835{
836 struct audio_in *audio = &the_audio_in;
837 int rc;
838 int encid;
839
840 mutex_lock(&audio->lock);
841 if (audio->opened) {
842 rc = -EBUSY;
843 goto done;
844 }
Santosh Mardifdc227a2011-07-11 17:20:34 +0530845 audio->phys = allocate_contiguous_ebi_nomap(DMASZ, SZ_4K);
846 if (audio->phys) {
847 audio->map_v_read = msm_subsystem_map_buffer(
848 audio->phys, DMASZ,
849 MSM_SUBSYSTEM_MAP_KADDR, NULL, 0);
850 if (IS_ERR(audio->map_v_read)) {
851 MM_ERR("could not map read phys buffers\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700852 rc = -ENOMEM;
Santosh Mardifdc227a2011-07-11 17:20:34 +0530853 free_contiguous_memory_by_paddr(audio->phys);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700854 goto done;
855 }
Santosh Mardifdc227a2011-07-11 17:20:34 +0530856 audio->data = audio->map_v_read->vaddr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700857 } else {
858 MM_ERR("could not allocate read buffers\n");
859 rc = -ENOMEM;
860 goto done;
861 }
862 MM_DBG("Memory addr = 0x%8x phy addr = 0x%8x\n",\
863 (int) audio->data, (int) audio->phys);
864 if ((file->f_mode & FMODE_WRITE) &&
865 (file->f_mode & FMODE_READ)) {
866 rc = -EACCES;
867 MM_ERR("Non tunnel encoding is not supported\n");
868 goto done;
869 } else if (!(file->f_mode & FMODE_WRITE) &&
870 (file->f_mode & FMODE_READ)) {
871 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
872 MM_DBG("Opened for tunnel mode encoding\n");
873 } else {
874 rc = -EACCES;
875 goto done;
876 }
877 /* Settings will be re-config at AUDIO_SET_CONFIG,
878 * but at least we need to have initial config
879 */
880 audio->channel_mode = AUDREC_CMD_MODE_MONO;
881 audio->buffer_size = MONO_DATA_SIZE_1024;
882 audio->samp_rate = 8000;
883 audio->enc_type = ENC_TYPE_EXT_WAV | audio->mode;
884
885 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
886 &audio->queue_ids);
887 if (encid < 0) {
888 MM_ERR("No free encoder available\n");
889 rc = -ENODEV;
890 goto done;
891 }
892 audio->enc_id = encid;
893
894 rc = msm_adsp_get(audio->module_name, &audio->audrec,
895 &audrec_adsp_ops, audio);
896
897 if (rc) {
898 audpreproc_aenc_free(audio->enc_id);
899 goto done;
900 }
901
902 audio->stopped = 0;
903 audio->source = 0;
904 audio->abort = 0;
905 audpcm_in_flush(audio);
906 audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS |
907 AUDDEV_EVT_FREQ_CHG |
908 AUDDEV_EVT_VOICE_STATE_CHG;
909
910 audio->voice_state = msm_get_voice_state();
911 rc = auddev_register_evt_listner(audio->device_events,
912 AUDDEV_CLNT_ENC, audio->enc_id,
913 pcm_in_listener, (void *) audio);
914 if (rc) {
915 MM_ERR("failed to register device event listener\n");
916 goto evt_error;
917 }
918 file->private_data = audio;
919 audio->opened = 1;
920 rc = 0;
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +0530921 audio->build_id = socinfo_get_build_id();
922 MM_ERR("build id used is = %s\n", audio->build_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700923done:
924 mutex_unlock(&audio->lock);
925 return rc;
926evt_error:
927 msm_adsp_put(audio->audrec);
928 audpreproc_aenc_free(audio->enc_id);
929 mutex_unlock(&audio->lock);
930 return rc;
931}
932
933static const struct file_operations audio_in_fops = {
934 .owner = THIS_MODULE,
935 .open = audpcm_in_open,
936 .release = audpcm_in_release,
937 .read = audpcm_in_read,
938 .write = audpcm_in_write,
939 .unlocked_ioctl = audpcm_in_ioctl,
940};
941
942struct miscdevice audio_in_misc = {
943 .minor = MISC_DYNAMIC_MINOR,
944 .name = "msm_pcm_in",
945 .fops = &audio_in_fops,
946};
947
948static int __init audpcm_in_init(void)
949{
950 mutex_init(&the_audio_in.lock);
951 mutex_init(&the_audio_in.read_lock);
952 spin_lock_init(&the_audio_in.dsp_lock);
953 spin_lock_init(&the_audio_in.dev_lock);
954 init_waitqueue_head(&the_audio_in.wait);
955 init_waitqueue_head(&the_audio_in.wait_enable);
956 return misc_register(&audio_in_misc);
957}
958
959device_initcall(audpcm_in_init);