blob: 851980db60733d2300cecf12a74462291e40ab11 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/qdsp5/audio_pcm_in.c
2 *
3 * pcm audio input device
4 *
5 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
6 *
7 * This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_pcm_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.h>
33
34#include <mach/msm_memtypes.h>
35#include <linux/memory_alloc.h>
36
37#include <asm/atomic.h>
38#include <asm/ioctls.h>
39#include <mach/msm_adsp.h>
40#include <mach/msm_rpcrouter.h>
41
42#include "audmgr.h"
43
44#include <mach/qdsp5/qdsp5audpreproc.h>
45#include <mach/qdsp5/qdsp5audpreproccmdi.h>
46#include <mach/qdsp5/qdsp5audpreprocmsg.h>
47#include <mach/qdsp5/qdsp5audreccmdi.h>
48#include <mach/qdsp5/qdsp5audrecmsg.h>
49#include <mach/debug_mm.h>
50
51/* FRAME_NUM must be a power of two */
52#define FRAME_NUM (8)
53#define FRAME_SIZE (2052 * 2)
54#define MONO_DATA_SIZE (2048)
55#define STEREO_DATA_SIZE (MONO_DATA_SIZE * 2)
56#define DMASZ (FRAME_SIZE * FRAME_NUM)
Manish Dewangan5a369502011-07-25 20:00:41 +053057#define MSM_AUD_BUFFER_UPDATE_WAIT_MS 2000
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070058
59struct buffer {
60 void *data;
61 uint32_t size;
62 uint32_t read;
63 uint32_t addr;
64};
65
66struct audio_in {
67 struct buffer in[FRAME_NUM];
68
69 spinlock_t dsp_lock;
70
71 atomic_t in_bytes;
72
73 struct mutex lock;
74 struct mutex read_lock;
75 wait_queue_head_t wait;
76
77 struct msm_adsp_module *audpre;
78 struct msm_adsp_module *audrec;
79 const char *module_name;
80 unsigned queue_ids;
81 uint16_t enc_id; /* Session Id */
82
83 /* configuration to use on next enable */
84 uint32_t samp_rate;
85 uint32_t channel_mode;
86 uint32_t buffer_size; /* 2048 for mono, 4096 for stereo */
87 uint32_t enc_type; /* 0 for PCM */
88 uint32_t mode; /* Tunnel for PCM */
89 uint32_t dsp_cnt;
90 uint32_t in_head; /* next buffer dsp will write */
91 uint32_t in_tail; /* next buffer read() will read */
92 uint32_t in_count; /* number of buffers available to read() */
93
94 unsigned short samp_rate_index;
95 uint32_t audrec_obj_idx ;
96
97 struct audmgr audmgr;
98
99 /* data allocated for various buffers */
100 char *data;
101 dma_addr_t phys;
102
103 int opened;
104 int enabled;
105 int running;
106 int stopped; /* set when stopped, cleared on flush */
107
108 /* audpre settings */
109 int tx_agc_enable;
110 audpreproc_cmd_cfg_agc_params tx_agc_cfg;
111 int ns_enable;
112 audpreproc_cmd_cfg_ns_params ns_cfg;
113 /* For different sample rate, the coeff might be different. *
114 * All the coeff should be passed from user space */
115 int iir_enable;
116 audpreproc_cmd_cfg_iir_tuning_filter_params iir_cfg;
117};
118
119static int audpcm_in_dsp_enable(struct audio_in *audio, int enable);
120static int audpcm_in_encmem_config(struct audio_in *audio);
121static int audpcm_in_encparam_config(struct audio_in *audio);
122static int audpcm_in_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt);
123static void audpcm_in_flush(struct audio_in *audio);
124static int audio_dsp_set_tx_agc(struct audio_in *audio);
125static int audio_dsp_set_ns(struct audio_in *audio);
126static int audio_dsp_set_iir(struct audio_in *audio);
127
128static unsigned convert_dsp_samp_index(unsigned index)
129{
130 switch (index) {
131 case 48000: return AUDREC_CMD_SAMP_RATE_INDX_48000;
132 case 44100: return AUDREC_CMD_SAMP_RATE_INDX_44100;
133 case 32000: return AUDREC_CMD_SAMP_RATE_INDX_32000;
134 case 24000: return AUDREC_CMD_SAMP_RATE_INDX_24000;
135 case 22050: return AUDREC_CMD_SAMP_RATE_INDX_22050;
136 case 16000: return AUDREC_CMD_SAMP_RATE_INDX_16000;
137 case 12000: return AUDREC_CMD_SAMP_RATE_INDX_12000;
138 case 11025: return AUDREC_CMD_SAMP_RATE_INDX_11025;
139 case 8000: return AUDREC_CMD_SAMP_RATE_INDX_8000;
140 default: return AUDREC_CMD_SAMP_RATE_INDX_11025;
141 }
142}
143
144static unsigned convert_samp_rate(unsigned hz)
145{
146 switch (hz) {
147 case 48000: return RPC_AUD_DEF_SAMPLE_RATE_48000;
148 case 44100: return RPC_AUD_DEF_SAMPLE_RATE_44100;
149 case 32000: return RPC_AUD_DEF_SAMPLE_RATE_32000;
150 case 24000: return RPC_AUD_DEF_SAMPLE_RATE_24000;
151 case 22050: return RPC_AUD_DEF_SAMPLE_RATE_22050;
152 case 16000: return RPC_AUD_DEF_SAMPLE_RATE_16000;
153 case 12000: return RPC_AUD_DEF_SAMPLE_RATE_12000;
154 case 11025: return RPC_AUD_DEF_SAMPLE_RATE_11025;
155 case 8000: return RPC_AUD_DEF_SAMPLE_RATE_8000;
156 default: return RPC_AUD_DEF_SAMPLE_RATE_11025;
157 }
158}
159
160static unsigned convert_samp_index(unsigned index)
161{
162 switch (index) {
163 case RPC_AUD_DEF_SAMPLE_RATE_48000: return 48000;
164 case RPC_AUD_DEF_SAMPLE_RATE_44100: return 44100;
165 case RPC_AUD_DEF_SAMPLE_RATE_32000: return 32000;
166 case RPC_AUD_DEF_SAMPLE_RATE_24000: return 24000;
167 case RPC_AUD_DEF_SAMPLE_RATE_22050: return 22050;
168 case RPC_AUD_DEF_SAMPLE_RATE_16000: return 16000;
169 case RPC_AUD_DEF_SAMPLE_RATE_12000: return 12000;
170 case RPC_AUD_DEF_SAMPLE_RATE_11025: return 11025;
171 case RPC_AUD_DEF_SAMPLE_RATE_8000: return 8000;
172 default: return 11025;
173 }
174}
175
176/* must be called with audio->lock held */
177static int audpcm_in_enable(struct audio_in *audio)
178{
179 struct audmgr_config cfg;
180 int rc;
181
182 if (audio->enabled)
183 return 0;
184
185 cfg.tx_rate = audio->samp_rate;
186 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
187 cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
188 cfg.codec = RPC_AUD_DEF_CODEC_PCM;
189 cfg.snd_method = RPC_SND_METHOD_MIDI;
190
191 rc = audmgr_enable(&audio->audmgr, &cfg);
192 if (rc < 0)
193 return rc;
194
195 if (msm_adsp_enable(audio->audpre)) {
196 MM_ERR("msm_adsp_enable(audpre) failed\n");
197 audmgr_disable(&audio->audmgr);
198 return -ENODEV;
199 }
200 if (msm_adsp_enable(audio->audrec)) {
201 audmgr_disable(&audio->audmgr);
202 msm_adsp_disable(audio->audpre);
203 MM_ERR("msm_adsp_enable(audrec) failed\n");
204 return -ENODEV;
205 }
206
207 audio->enabled = 1;
208 audpcm_in_dsp_enable(audio, 1);
209
210 return 0;
211}
212
213/* must be called with audio->lock held */
214static int audpcm_in_disable(struct audio_in *audio)
215{
216 if (audio->enabled) {
217 audio->enabled = 0;
218
219 audpcm_in_dsp_enable(audio, 0);
220
Manish Dewangan89a9f232012-02-09 17:14:40 +0530221 audio->stopped = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222 wake_up(&audio->wait);
223
224 msm_adsp_disable(audio->audrec);
225 msm_adsp_disable(audio->audpre);
226 audmgr_disable(&audio->audmgr);
227 }
228 return 0;
229}
230
231/* ------------------- dsp --------------------- */
232static void audpre_dsp_event(void *data, unsigned id, size_t len,
233 void (*getevent)(void *ptr, size_t len))
234{
235 uint16_t msg[2];
236 getevent(msg, sizeof(msg));
237
238 switch (id) {
239 case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
240 MM_INFO("type %d, status_flag %d\n", msg[0], msg[1]);
241 break;
242 case AUDPREPROC_MSG_ERROR_MSG_ID:
243 MM_ERR("err_index %d\n", msg[0]);
244 break;
245 case ADSP_MESSAGE_ID:
246 MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
247 break;
248 default:
249 MM_ERR("unknown event %d\n", id);
250 }
251}
252
253struct audio_frame {
254 uint16_t count_low;
255 uint16_t count_high;
256 uint16_t bytes;
257 uint16_t unknown;
258 unsigned char samples[];
259} __packed;
260
261static void audpcm_in_get_dsp_frames(struct audio_in *audio)
262{
263 struct audio_frame *frame;
264 uint32_t index;
265 unsigned long flags;
266
267 index = audio->in_head;
268
269 frame = (void *) (((char *)audio->in[index].data) -
270 sizeof(*frame));
271 spin_lock_irqsave(&audio->dsp_lock, flags);
272 audio->in[index].size = frame->bytes;
273
274 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
275
276 /* If overflow, move the tail index foward. */
277 if (audio->in_head == audio->in_tail) {
278 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
279 MM_ERR("Error! not able to keep up the read\n");
280 } else
281 audio->in_count++;
282
283 audpcm_in_dsp_read_buffer(audio, audio->dsp_cnt++);
284 spin_unlock_irqrestore(&audio->dsp_lock, flags);
285
286 wake_up(&audio->wait);
287}
288
289static void audrec_dsp_event(void *data, unsigned id, size_t len,
290 void (*getevent)(void *ptr, size_t len))
291{
292 struct audio_in *audio = NULL;
293 uint16_t msg[3];
294
295 if (data)
296 audio = data;
297 else {
298 MM_ERR("invalid data for event %x\n", id);
299 return;
300 }
301
302 getevent(msg, sizeof(msg));
303
304 switch (id) {
305 case AUDREC_MSG_CMD_CFG_DONE_MSG: {
306 if (msg[0] & AUDREC_MSG_CFG_DONE_ENC_ENA) {
307 audio->audrec_obj_idx = msg[1];
308 MM_INFO("CFG ENABLED\n");
309 audpcm_in_encmem_config(audio);
310 } else {
311 MM_INFO("CFG SLEEP\n");
312 audio->running = 0;
313 audio->tx_agc_enable = 0;
314 audio->ns_enable = 0;
315 audio->iir_enable = 0;
316 }
317 break;
318 }
319 case AUDREC_MSG_CMD_AREC_MEM_CFG_DONE_MSG: {
320 MM_DBG("AREC_MEM_CFG_DONE_MSG\n");
321 audpcm_in_encparam_config(audio);
322 break;
323 }
324 case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
325 MM_INFO("PARAM CFG DONE\n");
326 audio->running = 1;
327 audio_dsp_set_tx_agc(audio);
328 audio_dsp_set_ns(audio);
329 audio_dsp_set_iir(audio);
330 break;
331 }
332 case AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG: {
333 MM_DBG("ERROR %x\n", msg[0]);
334 break;
335 }
336 case AUDREC_MSG_PACKET_READY_MSG: {
337 struct audrec_msg_packet_ready_msg pkt_ready_msg;
338
339 getevent(&pkt_ready_msg, AUDREC_MSG_PACKET_READY_MSG_LEN);
340 MM_DBG("UP_PACKET_READY_MSG: write cnt msw %d \
341 write cnt lsw %d read cnt msw %d read cnt lsw %d \n",\
342 pkt_ready_msg.pkt_counter_msw, \
343 pkt_ready_msg.pkt_counter_lsw, \
344 pkt_ready_msg.pkt_read_cnt_msw, \
345 pkt_ready_msg.pkt_read_cnt_lsw);
346
347 audpcm_in_get_dsp_frames(audio);
348 break;
349 }
350 case ADSP_MESSAGE_ID: {
351 MM_DBG("Received ADSP event: module \
352 enable/disable(audrectask)\n");
353 break;
354 }
355 default:
356 MM_ERR("unknown event %d\n", id);
357 }
358}
359
360static struct msm_adsp_ops audpre_adsp_ops = {
361 .event = audpre_dsp_event,
362};
363
364static struct msm_adsp_ops audrec_adsp_ops = {
365 .event = audrec_dsp_event,
366};
367
368
369#define audio_send_queue_pre(audio, cmd, len) \
370 msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
371
372#define audio_send_queue_recbs(audio, cmd, len) \
373 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
374 cmd, len)
375#define audio_send_queue_rec(audio, cmd, len) \
376 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
377 cmd, len)
378
379static int audio_dsp_set_tx_agc(struct audio_in *audio)
380{
381 audpreproc_cmd_cfg_agc_params cmd;
382
383 memset(&cmd, 0, sizeof(cmd));
384
385 audio->tx_agc_cfg.cmd_id = AUDPREPROC_CMD_CFG_AGC_PARAMS;
386 if (audio->tx_agc_enable) {
387 /* cmd.tx_agc_param_mask = 0xFE00 from sample code */
388 audio->tx_agc_cfg.tx_agc_param_mask =
389 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_SLOPE) |
390 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_TH) |
391 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_EXP_SLOPE) |
392 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_EXP_TH) |
393 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_AIG_FLAG) |
394 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_STATIC_GAIN) |
395 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_TX_AGC_ENA_FLAG);
396 audio->tx_agc_cfg.tx_agc_enable_flag =
397 AUDPREPROC_CMD_TX_AGC_ENA_FLAG_ENA;
398 /* cmd.param_mask = 0xFFF0 from sample code */
399 audio->tx_agc_cfg.param_mask =
400 (1 << AUDPREPROC_CMD_PARAM_MASK_RMS_TAY) |
401 (1 << AUDPREPROC_CMD_PARAM_MASK_RELEASEK) |
402 (1 << AUDPREPROC_CMD_PARAM_MASK_DELAY) |
403 (1 << AUDPREPROC_CMD_PARAM_MASK_ATTACKK) |
404 (1 << AUDPREPROC_CMD_PARAM_MASK_LEAKRATE_SLOW) |
405 (1 << AUDPREPROC_CMD_PARAM_MASK_LEAKRATE_FAST) |
406 (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_RELEASEK) |
407 (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_MIN) |
408 (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_MAX) |
409 (1 << AUDPREPROC_CMD_PARAM_MASK_LEAK_UP) |
410 (1 << AUDPREPROC_CMD_PARAM_MASK_LEAK_DOWN) |
411 (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_ATTACKK);
412 } else {
413 audio->tx_agc_cfg.tx_agc_param_mask =
414 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_TX_AGC_ENA_FLAG);
415 audio->tx_agc_cfg.tx_agc_enable_flag =
416 AUDPREPROC_CMD_TX_AGC_ENA_FLAG_DIS;
417 }
418 cmd = audio->tx_agc_cfg;
419
420 return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
421}
422
423static int audio_enable_tx_agc(struct audio_in *audio, int enable)
424{
425 if (audio->tx_agc_enable != enable) {
426 audio->tx_agc_enable = enable;
427 if (audio->running)
428 audio_dsp_set_tx_agc(audio);
429 }
430 return 0;
431}
432
433static int audio_dsp_set_ns(struct audio_in *audio)
434{
435 audpreproc_cmd_cfg_ns_params cmd;
436
437 memset(&cmd, 0, sizeof(cmd));
438
439 audio->ns_cfg.cmd_id = AUDPREPROC_CMD_CFG_NS_PARAMS;
440
441 if (audio->ns_enable) {
442 /* cmd.ec_mode_new is fixed as 0x0064 when enable
443 * from sample code */
444 audio->ns_cfg.ec_mode_new =
445 AUDPREPROC_CMD_EC_MODE_NEW_NS_ENA |
446 AUDPREPROC_CMD_EC_MODE_NEW_HB_ENA |
447 AUDPREPROC_CMD_EC_MODE_NEW_VA_ENA;
448 } else {
449 audio->ns_cfg.ec_mode_new =
450 AUDPREPROC_CMD_EC_MODE_NEW_NLMS_DIS |
451 AUDPREPROC_CMD_EC_MODE_NEW_DES_DIS |
452 AUDPREPROC_CMD_EC_MODE_NEW_NS_DIS |
453 AUDPREPROC_CMD_EC_MODE_NEW_CNI_DIS |
454 AUDPREPROC_CMD_EC_MODE_NEW_NLES_DIS |
455 AUDPREPROC_CMD_EC_MODE_NEW_HB_DIS |
456 AUDPREPROC_CMD_EC_MODE_NEW_VA_DIS |
457 AUDPREPROC_CMD_EC_MODE_NEW_PCD_DIS |
458 AUDPREPROC_CMD_EC_MODE_NEW_FEHI_DIS |
459 AUDPREPROC_CMD_EC_MODE_NEW_NEHI_DIS |
460 AUDPREPROC_CMD_EC_MODE_NEW_NLPP_DIS |
461 AUDPREPROC_CMD_EC_MODE_NEW_FNE_DIS |
462 AUDPREPROC_CMD_EC_MODE_NEW_PRENLMS_DIS;
463 }
464 cmd = audio->ns_cfg;
465
466 return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
467}
468
469static int audio_enable_ns(struct audio_in *audio, int enable)
470{
471 if (audio->ns_enable != enable) {
472 audio->ns_enable = enable;
473 if (audio->running)
474 audio_dsp_set_ns(audio);
475 }
476 return 0;
477}
478
479static int audio_dsp_set_iir(struct audio_in *audio)
480{
481 audpreproc_cmd_cfg_iir_tuning_filter_params cmd;
482
483 memset(&cmd, 0, sizeof(cmd));
484
485 audio->iir_cfg.cmd_id = AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS;
486
487 if (audio->iir_enable)
488 /* cmd.active_flag is 0xFFFF from sample code but 0x0001 here */
489 audio->iir_cfg.active_flag = AUDPREPROC_CMD_IIR_ACTIVE_FLAG_ENA;
490 else
491 audio->iir_cfg.active_flag = AUDPREPROC_CMD_IIR_ACTIVE_FLAG_DIS;
492
493 cmd = audio->iir_cfg;
494
495 return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
496}
497
498static int audio_enable_iir(struct audio_in *audio, int enable)
499{
500 if (audio->iir_enable != enable) {
501 audio->iir_enable = enable;
502 if (audio->running)
503 audio_dsp_set_iir(audio);
504 }
505 return 0;
506}
507
508static int audpcm_in_dsp_enable(struct audio_in *audio, int enable)
509{
510 struct audrec_cmd_enc_cfg cmd;
511
512 memset(&cmd, 0, sizeof(cmd));
513 cmd.cmd_id = AUDREC_CMD_ENC_CFG;
514
515 cmd.audrec_enc_type = (audio->enc_type & 0xFF) |
516 (enable ? AUDREC_CMD_ENC_ENA : AUDREC_CMD_ENC_DIS);
517 /* Don't care */
518 cmd.audrec_obj_idx = audio->audrec_obj_idx;
519
520 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
521}
522
523static int audpcm_in_encmem_config(struct audio_in *audio)
524{
525 struct audrec_cmd_arecmem_cfg cmd;
526 uint16_t cnt = 0;
527 uint16_t *data = (void *) audio->data;
528
529 memset(&cmd, 0, sizeof(cmd));
530
531 cmd.cmd_id = AUDREC_CMD_ARECMEM_CFG;
532 cmd.audrec_obj_idx = audio->audrec_obj_idx;
533 /* Rate at which packet complete message comes */
534 cmd.audrec_up_pkt_intm_cnt = 1;
535 cmd.audrec_extpkt_buffer_msw = audio->phys >> 16;
536 cmd.audrec_extpkt_buffer_lsw = audio->phys;
537 /* Max Buffer no available for frames */
538 cmd.audrec_extpkt_buffer_num = FRAME_NUM;
539
540 /* prepare buffer pointers:
541 * Mono: 1024 samples + 4 halfword header
542 * Stereo: 2048 samples + 4 halfword header
543 */
544 for (cnt = 0; cnt < FRAME_NUM; cnt++) {
545 audio->in[cnt].data = data + 4;
546 data += (4 + (audio->channel_mode ? 2048 : 1024));
547 }
548
549 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
550}
551
552static int audpcm_in_encparam_config(struct audio_in *audio)
553{
554 struct audrec_cmd_arecparam_wav_cfg cmd;
555
556 memset(&cmd, 0, sizeof(cmd));
557 cmd.common.cmd_id = AUDREC_CMD_ARECPARAM_CFG;
558 cmd.common.audrec_obj_idx = audio->audrec_obj_idx;
559 cmd.samp_rate_idx = audio->samp_rate_index;
560 cmd.stereo_mode = audio->channel_mode; /* 0 for mono, 1 for stereo */
561
562 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
563}
564
565static int audpcm_in_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt)
566{
567 audrec_cmd_packet_ext_ptr cmd;
568
569 memset(&cmd, 0, sizeof(cmd));
570 cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
571 cmd.type = audio->audrec_obj_idx;
572 cmd.curr_rec_count_msw = read_cnt >> 16;
573 cmd.curr_rec_count_lsw = read_cnt;
574
575 return audio_send_queue_recbs(audio, &cmd, sizeof(cmd));
576}
577
578/* ------------------- device --------------------- */
579
580static void audpcm_in_flush(struct audio_in *audio)
581{
582 int i;
583
584 audio->dsp_cnt = 0;
585 audio->in_head = 0;
586 audio->in_tail = 0;
587 audio->in_count = 0;
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530588 for (i = FRAME_NUM-1; i >= 0; i--) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700589 audio->in[i].size = 0;
590 audio->in[i].read = 0;
591 }
592}
593
594static long audpcm_in_ioctl(struct file *file,
595 unsigned int cmd, unsigned long arg)
596{
597 struct audio_in *audio = file->private_data;
598 int rc = 0;
599
600 if (cmd == AUDIO_GET_STATS) {
601 struct msm_audio_stats stats;
602 stats.byte_count = atomic_read(&audio->in_bytes);
603 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
604 return -EFAULT;
605 return 0;
606 }
607
608 mutex_lock(&audio->lock);
609 switch (cmd) {
610 case AUDIO_START: {
611 rc = audpcm_in_enable(audio);
612 audio->stopped = 0;
613 break;
614 }
615 case AUDIO_STOP:
616 rc = audpcm_in_disable(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700617 break;
618 case AUDIO_FLUSH:
619 if (audio->stopped) {
620 /* Make sure we're stopped and we wake any threads
621 * that might be blocked holding the read_lock.
622 * While audio->stopped read threads will always
623 * exit immediately.
624 */
625 wake_up(&audio->wait);
626 mutex_lock(&audio->read_lock);
627 audpcm_in_flush(audio);
628 mutex_unlock(&audio->read_lock);
629 }
630 break;
631 case AUDIO_SET_CONFIG: {
632 struct msm_audio_config cfg;
633
634 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
635 rc = -EFAULT;
636 break;
637 }
638 if (cfg.channel_count == 1) {
639 cfg.channel_count = AUDREC_CMD_STEREO_MODE_MONO;
640 } else if (cfg.channel_count == 2) {
641 cfg.channel_count = AUDREC_CMD_STEREO_MODE_STEREO;
642 } else {
643 rc = -EINVAL;
644 break;
645 }
646
647 audio->samp_rate = convert_samp_rate(cfg.sample_rate);
648 audio->samp_rate_index =
649 convert_dsp_samp_index(cfg.sample_rate);
650 audio->channel_mode = cfg.channel_count;
651 audio->buffer_size =
652 audio->channel_mode ? STEREO_DATA_SIZE
653 : MONO_DATA_SIZE;
654 break;
655 }
656 case AUDIO_GET_CONFIG: {
657 struct msm_audio_config cfg;
658 cfg.buffer_size = audio->buffer_size;
659 cfg.buffer_count = FRAME_NUM;
660 cfg.sample_rate = convert_samp_index(audio->samp_rate);
661 if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO)
662 cfg.channel_count = 1;
663 else
664 cfg.channel_count = 2;
665 cfg.type = 0;
666 cfg.unused[0] = 0;
667 cfg.unused[1] = 0;
668 cfg.unused[2] = 0;
669 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
670 rc = -EFAULT;
671 break;
672 }
673 default:
674 rc = -EINVAL;
675 }
676 mutex_unlock(&audio->lock);
677 return rc;
678}
679
680static ssize_t audpcm_in_read(struct file *file,
681 char __user *buf,
682 size_t count, loff_t *pos)
683{
684 struct audio_in *audio = file->private_data;
685 unsigned long flags;
686 const char __user *start = buf;
687 void *data;
688 uint32_t index;
689 uint32_t size;
690 int rc = 0;
691
692 mutex_lock(&audio->read_lock);
693 while (count > 0) {
Manish Dewangan5a369502011-07-25 20:00:41 +0530694 rc = wait_event_interruptible_timeout(
695 audio->wait, (audio->in_count > 0) || audio->stopped,
696 msecs_to_jiffies(MSM_AUD_BUFFER_UPDATE_WAIT_MS));
697 if (rc == 0) {
698 rc = -ETIMEDOUT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700699 break;
Manish Dewangan5a369502011-07-25 20:00:41 +0530700 } else if (rc < 0) {
701 break;
702 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700703
704 if (audio->stopped && !audio->in_count) {
705 rc = 0;/* End of File */
706 break;
707 }
708
709 index = audio->in_tail;
710 data = (uint8_t *) audio->in[index].data;
711 size = audio->in[index].size;
712 if (count >= size) {
713 /* order the reads on the buffer */
714 dma_coherent_post_ops();
715 if (copy_to_user(buf, data, size)) {
716 rc = -EFAULT;
717 break;
718 }
719 spin_lock_irqsave(&audio->dsp_lock, flags);
720 if (index != audio->in_tail) {
721 /* overrun -- data is invalid and we need to
722 * retry
723 */
724 spin_unlock_irqrestore(&audio->dsp_lock, flags);
725 continue;
726 }
727 audio->in[index].size = 0;
728 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
729 audio->in_count--;
730 spin_unlock_irqrestore(&audio->dsp_lock, flags);
731 count -= size;
732 buf += size;
733 } else {
734 MM_ERR("short read\n");
735 break;
736 }
737 }
738 mutex_unlock(&audio->read_lock);
739
740 if (buf > start)
741 return buf - start;
742
743 return rc;
744}
745
746static ssize_t audpcm_in_write(struct file *file,
747 const char __user *buf,
748 size_t count, loff_t *pos)
749{
750 return -EINVAL;
751}
752
753static int audpcm_in_release(struct inode *inode, struct file *file)
754{
755 struct audio_in *audio = file->private_data;
756
757 mutex_lock(&audio->lock);
758 audpcm_in_disable(audio);
759 audpcm_in_flush(audio);
760 audpreproc_aenc_free(audio->enc_id);
761 msm_adsp_put(audio->audrec);
762 msm_adsp_put(audio->audpre);
763 audio->audrec = NULL;
764 audio->audpre = NULL;
765 audio->opened = 0;
766 if (audio->data) {
767 free_contiguous_memory((void *)audio->data);
768 audio->data = NULL;
769 }
770 mutex_unlock(&audio->lock);
771 return 0;
772}
773
774static struct audio_in the_audio_in;
775
776static int audpcm_in_open(struct inode *inode, struct file *file)
777{
778 struct audio_in *audio = &the_audio_in;
779 int rc;
780
781 int encid;
782 mutex_lock(&audio->lock);
783 if (audio->opened) {
784 rc = -EBUSY;
785 goto done;
786 }
787
788 /* Settings will be re-config at AUDIO_SET_CONFIG,
789 * but at least we need to have initial config
790 */
791 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
792 audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_11025;
793 audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_11025;
794 audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
795 audio->buffer_size = MONO_DATA_SIZE;
796 audio->enc_type = AUDREC_CMD_TYPE_0_INDEX_WAV | audio->mode;
797
798 rc = audmgr_open(&audio->audmgr);
799 if (rc)
800 goto done;
801 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
802 &audio->queue_ids);
803 if (encid < 0) {
804 MM_ERR("No free encoder available\n");
805 rc = -ENODEV;
806 goto done;
807 }
808 audio->enc_id = encid;
809
810 rc = msm_adsp_get(audio->module_name, &audio->audrec,
811 &audrec_adsp_ops, audio);
812 if (rc) {
813 audpreproc_aenc_free(audio->enc_id);
814 goto done;
815 }
816
817 rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
818 &audpre_adsp_ops, audio);
819 if (rc) {
820 msm_adsp_put(audio->audrec);
821 audpreproc_aenc_free(audio->enc_id);
822 goto done;
823 }
824
825 audio->dsp_cnt = 0;
826 audio->stopped = 0;
827
828 audpcm_in_flush(audio);
829
830 audio->data = allocate_contiguous_memory(DMASZ, MEMTYPE_EBI1,
831 SZ_4K, 0);
832 if (!audio->data) {
833 MM_ERR("could not allocate read buffers\n");
834 rc = -ENOMEM;
835 goto evt_error;
836 } else {
837 audio->phys = memory_pool_node_paddr(audio->data);
838 if (!audio->phys) {
839 MM_ERR("could not get physical address\n");
840 rc = -ENOMEM;
841 free_contiguous_memory(audio->data);
842 goto evt_error;
843 }
844 MM_DBG("read buf: phy addr 0x%08x kernel addr 0x%08x\n",
845 audio->phys, (int)audio->data);
846 }
847
848 file->private_data = audio;
849 audio->opened = 1;
850 rc = 0;
851done:
852 mutex_unlock(&audio->lock);
853 return rc;
854evt_error:
855 msm_adsp_put(audio->audrec);
856 msm_adsp_put(audio->audpre);
857 audpreproc_aenc_free(audio->enc_id);
858 mutex_unlock(&audio->lock);
859 return rc;
860}
861
862static long audpre_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
863{
864 struct audio_in *audio = file->private_data;
865 int rc = 0, enable;
866 uint16_t enable_mask;
867
868 mutex_lock(&audio->lock);
869 switch (cmd) {
870 case AUDIO_ENABLE_AUDPRE:
871 if (copy_from_user(&enable_mask, (void *) arg,
872 sizeof(enable_mask))) {
873 rc = -EFAULT;
874 break;
875 }
876
877 enable = (enable_mask & AGC_ENABLE) ? 1 : 0;
878 audio_enable_tx_agc(audio, enable);
879 enable = (enable_mask & NS_ENABLE) ? 1 : 0;
880 audio_enable_ns(audio, enable);
881 enable = (enable_mask & TX_IIR_ENABLE) ? 1 : 0;
882 audio_enable_iir(audio, enable);
883 break;
884
885 case AUDIO_SET_AGC:
886 if (copy_from_user(&audio->tx_agc_cfg, (void *) arg,
887 sizeof(audio->tx_agc_cfg)))
888 rc = -EFAULT;
889 break;
890
891 case AUDIO_SET_NS:
892 if (copy_from_user(&audio->ns_cfg, (void *) arg,
893 sizeof(audio->ns_cfg)))
894 rc = -EFAULT;
895 break;
896
897 case AUDIO_SET_TX_IIR:
898 if (copy_from_user(&audio->iir_cfg, (void *) arg,
899 sizeof(audio->iir_cfg)))
900 rc = -EFAULT;
901 break;
902
903 default:
904 rc = -EINVAL;
905 }
906
907 mutex_unlock(&audio->lock);
908 return rc;
909}
910
911static int audpre_open(struct inode *inode, struct file *file)
912{
913 struct audio_in *audio = &the_audio_in;
914
915 file->private_data = audio;
916
917 return 0;
918}
919
920static const struct file_operations audio_fops = {
921 .owner = THIS_MODULE,
922 .open = audpcm_in_open,
923 .release = audpcm_in_release,
924 .read = audpcm_in_read,
925 .write = audpcm_in_write,
926 .unlocked_ioctl = audpcm_in_ioctl,
927};
928
929static struct miscdevice audpcm_in_misc = {
930 .minor = MISC_DYNAMIC_MINOR,
931 .name = "msm_pcm_in",
932 .fops = &audio_fops,
933};
934
935static const struct file_operations audpre_fops = {
936 .owner = THIS_MODULE,
937 .open = audpre_open,
938 .unlocked_ioctl = audpre_ioctl,
939};
940
941static struct miscdevice audpre_misc = {
942 .minor = MISC_DYNAMIC_MINOR,
943 .name = "msm_preproc_ctl",
944 .fops = &audpre_fops,
945};
946
947static int __init audpcm_in_init(void)
948{
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 init_waitqueue_head(&the_audio_in.wait);
954 return misc_register(&audpcm_in_misc) || misc_register(&audpre_misc);
955}
956device_initcall(audpcm_in_init);