blob: 6fc2ac03be46853973dba630dfd0c1679166c7da [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/qdsp5/audio_in.c
2 *
3 * pcm audio input device
4 *
5 * Copyright (C) 2008 Google, Inc.
6 * Copyright (C) 2008 HTC Corporation
Duy Truong790f06d2013-02-13 16:38:12 -08007 * Copyright (c) 2009, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07008 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/fs.h>
22#include <linux/miscdevice.h>
23#include <linux/uaccess.h>
24#include <linux/kthread.h>
25#include <linux/wait.h>
26#include <linux/dma-mapping.h>
27
28#include <linux/delay.h>
29
30#include <linux/msm_audio_aac.h>
31
32#include <asm/atomic.h>
33#include <asm/ioctls.h>
34#include <mach/msm_adsp.h>
35#include <mach/msm_rpcrouter.h>
36
37#include "audmgr.h"
38
39#include <mach/qdsp5/qdsp5audpreproccmdi.h>
40#include <mach/qdsp5/qdsp5audpreprocmsg.h>
41#include <mach/qdsp5/qdsp5audreccmdi.h>
42#include <mach/qdsp5/qdsp5audrecmsg.h>
43#include <mach/debug_mm.h>
44
45/* FRAME_NUM must be a power of two */
46#define FRAME_NUM (8)
47#define FRAME_SIZE (2052 * 2)
48#define MONO_DATA_SIZE (2048)
49#define STEREO_DATA_SIZE (MONO_DATA_SIZE * 2)
50#define DMASZ (FRAME_SIZE * FRAME_NUM)
51
52struct buffer {
53 void *data;
54 uint32_t size;
55 uint32_t read;
56 uint32_t addr;
57};
58
59struct audio_in {
60 struct buffer in[FRAME_NUM];
61
62 spinlock_t dsp_lock;
63
64 atomic_t in_bytes;
65
66 struct mutex lock;
67 struct mutex read_lock;
68 wait_queue_head_t wait;
69
70 struct msm_adsp_module *audpre;
71 struct msm_adsp_module *audrec;
72
73 /* configuration to use on next enable */
74 uint32_t samp_rate;
75 uint32_t channel_mode;
76 uint32_t buffer_size; /* 2048 for mono, 4096 for stereo */
77 uint32_t type; /* 0 for PCM ,1 for AAC */
78 uint32_t bit_rate; /* bit rate for AAC */
79 uint32_t record_quality; /* record quality (bits/sample/channel)
80 for AAC*/
81 uint32_t buffer_cfg_ioctl; /* to allow any one of buffer set ioctl */
82 uint32_t dsp_cnt;
83 uint32_t in_head; /* next buffer dsp will write */
84 uint32_t in_tail; /* next buffer read() will read */
85 uint32_t in_count; /* number of buffers available to read() */
86
87 unsigned short samp_rate_index;
88
89 struct audmgr audmgr;
90
91 /* data allocated for various buffers */
92 char *data;
93 dma_addr_t phys;
94
95 int opened;
96 int enabled;
97 int running;
98 int stopped; /* set when stopped, cleared on flush */
99
100 /* audpre settings */
101 int tx_agc_enable;
102 audpreproc_cmd_cfg_agc_params tx_agc_cfg;
103 int ns_enable;
104 audpreproc_cmd_cfg_ns_params ns_cfg;
105 /* For different sample rate, the coeff might be different. *
106 * All the coeff should be passed from user space */
107 int iir_enable;
108 audpreproc_cmd_cfg_iir_tuning_filter_params iir_cfg;
109};
110
111static int audio_in_dsp_enable(struct audio_in *audio, int enable);
112static int audio_in_encoder_config(struct audio_in *audio);
113static int audio_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt);
114static void audio_flush(struct audio_in *audio);
115static int audio_dsp_set_tx_agc(struct audio_in *audio);
116static int audio_dsp_set_ns(struct audio_in *audio);
117static int audio_dsp_set_iir(struct audio_in *audio);
118
119static unsigned convert_dsp_samp_index(unsigned index)
120{
121 switch (index) {
122 case 48000: return AUDREC_CMD_SAMP_RATE_INDX_48000;
123 case 44100: return AUDREC_CMD_SAMP_RATE_INDX_44100;
124 case 32000: return AUDREC_CMD_SAMP_RATE_INDX_32000;
125 case 24000: return AUDREC_CMD_SAMP_RATE_INDX_24000;
126 case 22050: return AUDREC_CMD_SAMP_RATE_INDX_22050;
127 case 16000: return AUDREC_CMD_SAMP_RATE_INDX_16000;
128 case 12000: return AUDREC_CMD_SAMP_RATE_INDX_12000;
129 case 11025: return AUDREC_CMD_SAMP_RATE_INDX_11025;
130 case 8000: return AUDREC_CMD_SAMP_RATE_INDX_8000;
131 default: return AUDREC_CMD_SAMP_RATE_INDX_11025;
132 }
133}
134
135static unsigned convert_samp_rate(unsigned hz)
136{
137 switch (hz) {
138 case 48000: return RPC_AUD_DEF_SAMPLE_RATE_48000;
139 case 44100: return RPC_AUD_DEF_SAMPLE_RATE_44100;
140 case 32000: return RPC_AUD_DEF_SAMPLE_RATE_32000;
141 case 24000: return RPC_AUD_DEF_SAMPLE_RATE_24000;
142 case 22050: return RPC_AUD_DEF_SAMPLE_RATE_22050;
143 case 16000: return RPC_AUD_DEF_SAMPLE_RATE_16000;
144 case 12000: return RPC_AUD_DEF_SAMPLE_RATE_12000;
145 case 11025: return RPC_AUD_DEF_SAMPLE_RATE_11025;
146 case 8000: return RPC_AUD_DEF_SAMPLE_RATE_8000;
147 default: return RPC_AUD_DEF_SAMPLE_RATE_11025;
148 }
149}
150
151static unsigned convert_samp_index(unsigned index)
152{
153 switch (index) {
154 case RPC_AUD_DEF_SAMPLE_RATE_48000: return 48000;
155 case RPC_AUD_DEF_SAMPLE_RATE_44100: return 44100;
156 case RPC_AUD_DEF_SAMPLE_RATE_32000: return 32000;
157 case RPC_AUD_DEF_SAMPLE_RATE_24000: return 24000;
158 case RPC_AUD_DEF_SAMPLE_RATE_22050: return 22050;
159 case RPC_AUD_DEF_SAMPLE_RATE_16000: return 16000;
160 case RPC_AUD_DEF_SAMPLE_RATE_12000: return 12000;
161 case RPC_AUD_DEF_SAMPLE_RATE_11025: return 11025;
162 case RPC_AUD_DEF_SAMPLE_RATE_8000: return 8000;
163 default: return 11025;
164 }
165}
166
167/* must be called with audio->lock held */
168static int audio_in_enable(struct audio_in *audio)
169{
170 struct audmgr_config cfg;
171 int rc;
172
173 if (audio->enabled)
174 return 0;
175
176 cfg.tx_rate = audio->samp_rate;
177 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
178 cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
179 if (audio->type == AUDREC_CMD_TYPE_0_INDEX_WAV)
180 cfg.codec = RPC_AUD_DEF_CODEC_PCM;
181 else
182 cfg.codec = RPC_AUD_DEF_CODEC_AAC;
183 cfg.snd_method = RPC_SND_METHOD_MIDI;
184
185 rc = audmgr_enable(&audio->audmgr, &cfg);
186 if (rc < 0)
187 return rc;
188
189 if (msm_adsp_enable(audio->audpre)) {
190 MM_ERR("msm_adsp_enable(audpre) failed\n");
191 return -ENODEV;
192 }
193 if (msm_adsp_enable(audio->audrec)) {
194 MM_ERR("msm_adsp_enable(audrec) failed\n");
195 return -ENODEV;
196 }
197
198 audio->enabled = 1;
199 audio_in_dsp_enable(audio, 1);
200
201 return 0;
202}
203
204/* must be called with audio->lock held */
205static int audio_in_disable(struct audio_in *audio)
206{
207 if (audio->enabled) {
208 audio->enabled = 0;
209
210 audio_in_dsp_enable(audio, 0);
211
212 wake_up(&audio->wait);
213
214 msm_adsp_disable(audio->audrec);
215 msm_adsp_disable(audio->audpre);
216 audmgr_disable(&audio->audmgr);
217 }
218 return 0;
219}
220
221/* ------------------- dsp --------------------- */
222static void audpre_dsp_event(void *data, unsigned id, size_t len,
223 void (*getevent)(void *ptr, size_t len))
224{
225 uint16_t msg[2];
226 getevent(msg, sizeof(msg));
227
228 switch (id) {
229 case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
230 MM_INFO("type %d, status_flag %d\n", msg[0], msg[1]);
231 break;
232 case AUDPREPROC_MSG_ERROR_MSG_ID:
233 MM_INFO("err_index %d\n", msg[0]);
234 break;
235 case ADSP_MESSAGE_ID:
236 MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
237 break;
238 default:
239 MM_ERR("unknown event %d\n", id);
240 }
241}
242
243struct audio_frame {
244 uint16_t count_low;
245 uint16_t count_high;
246 uint16_t bytes;
247 uint16_t unknown;
248 unsigned char samples[];
249} __attribute__((packed));
250
251static void audio_in_get_dsp_frames(struct audio_in *audio)
252{
253 struct audio_frame *frame;
254 uint32_t index;
255 unsigned long flags;
256
257 index = audio->in_head;
258
259 /* XXX check for bogus frame size? */
260
261 frame = (void *) (((char *)audio->in[index].data) -
262 sizeof(*frame));
263 spin_lock_irqsave(&audio->dsp_lock, flags);
264 audio->in[index].size = frame->bytes;
265
266 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
267
268 /* If overflow, move the tail index foward. */
269 if (audio->in_head == audio->in_tail)
270 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
271 else
272 audio->in_count++;
273
274 audio_dsp_read_buffer(audio, audio->dsp_cnt++);
275 spin_unlock_irqrestore(&audio->dsp_lock, flags);
276
277 wake_up(&audio->wait);
278}
279
280static void audrec_dsp_event(void *data, unsigned id, size_t len,
281 void (*getevent)(void *ptr, size_t len))
282{
283 struct audio_in *audio = data;
284 uint16_t msg[3];
285 getevent(msg, sizeof(msg));
286
287 switch (id) {
288 case AUDREC_MSG_CMD_CFG_DONE_MSG:
289 if (msg[0] & AUDREC_MSG_CFG_DONE_TYPE_0_UPDATE) {
290 if (msg[0] & AUDREC_MSG_CFG_DONE_TYPE_0_ENA) {
291 MM_INFO("CFG ENABLED\n");
292 audio_in_encoder_config(audio);
293 } else {
294 MM_INFO("CFG SLEEP\n");
295 audio->running = 0;
296 audio->tx_agc_enable = 0;
297 audio->ns_enable = 0;
298 audio->iir_enable = 0;
299 }
300 } else {
301 MM_INFO("CMD_CFG_DONE %x\n", msg[0]);
302 }
303 break;
304 case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
305 MM_INFO("PARAM CFG DONE\n");
306 audio->running = 1;
307 audio_dsp_set_tx_agc(audio);
308 audio_dsp_set_ns(audio);
309 audio_dsp_set_iir(audio);
310 break;
311 }
312 case AUDREC_MSG_FATAL_ERR_MSG:
313 MM_ERR("ERROR %x\n", msg[0]);
314 break;
315 case AUDREC_MSG_PACKET_READY_MSG:
316/* REC_DBG("type %x, count %d", msg[0], (msg[1] | (msg[2] << 16))); */
317 audio_in_get_dsp_frames(audio);
318 break;
319 case ADSP_MESSAGE_ID:
320 MM_DBG("Received ADSP event: module \
321 enable/disable(audrectask)\n");
322 break;
323 default:
324 MM_ERR("unknown event %d\n", id);
325 }
326}
327
328struct msm_adsp_ops audpre_adsp_ops = {
329 .event = audpre_dsp_event,
330};
331
332struct msm_adsp_ops audrec_adsp_ops = {
333 .event = audrec_dsp_event,
334};
335
336
337#define audio_send_queue_pre(audio, cmd, len) \
338 msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
339#define audio_send_queue_recbs(audio, cmd, len) \
340 msm_adsp_write(audio->audrec, QDSP_uPAudRecBitStreamQueue, cmd, len)
341#define audio_send_queue_rec(audio, cmd, len) \
342 msm_adsp_write(audio->audrec, \
343 QDSP_uPAudRecCmdQueue, cmd, len)
344
345/* Convert Bit Rate to Record Quality field of DSP */
346static unsigned int bitrate_to_record_quality(unsigned int sample_rate,
347 unsigned int channel, unsigned int bit_rate) {
348 unsigned int temp;
349
350 temp = sample_rate * channel;
351 MM_DBG(" sample rate * channel = %d \n", temp);
352 /* To represent in Q12 fixed format */
353 temp = (bit_rate * 4096) / temp;
354 MM_DBG(" Record Quality = 0x%8x \n", temp);
355 return temp;
356}
357
358static int audio_dsp_set_tx_agc(struct audio_in *audio)
359{
360 audpreproc_cmd_cfg_agc_params cmd;
361
362 memset(&cmd, 0, sizeof(cmd));
363
364 audio->tx_agc_cfg.cmd_id = AUDPREPROC_CMD_CFG_AGC_PARAMS;
365 if (audio->tx_agc_enable) {
366 /* cmd.tx_agc_param_mask = 0xFE00 from sample code */
367 audio->tx_agc_cfg.tx_agc_param_mask =
368 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_SLOPE) |
369 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_TH) |
370 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_EXP_SLOPE) |
371 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_EXP_TH) |
372 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_AIG_FLAG) |
373 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_STATIC_GAIN) |
374 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_TX_AGC_ENA_FLAG);
375 audio->tx_agc_cfg.tx_agc_enable_flag =
376 AUDPREPROC_CMD_TX_AGC_ENA_FLAG_ENA;
377 /* cmd.param_mask = 0xFFF0 from sample code */
378 audio->tx_agc_cfg.param_mask =
379 (1 << AUDPREPROC_CMD_PARAM_MASK_RMS_TAY) |
380 (1 << AUDPREPROC_CMD_PARAM_MASK_RELEASEK) |
381 (1 << AUDPREPROC_CMD_PARAM_MASK_DELAY) |
382 (1 << AUDPREPROC_CMD_PARAM_MASK_ATTACKK) |
383 (1 << AUDPREPROC_CMD_PARAM_MASK_LEAKRATE_SLOW) |
384 (1 << AUDPREPROC_CMD_PARAM_MASK_LEAKRATE_FAST) |
385 (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_RELEASEK) |
386 (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_MIN) |
387 (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_MAX) |
388 (1 << AUDPREPROC_CMD_PARAM_MASK_LEAK_UP) |
389 (1 << AUDPREPROC_CMD_PARAM_MASK_LEAK_DOWN) |
390 (1 << AUDPREPROC_CMD_PARAM_MASK_AIG_ATTACKK);
391 } else {
392 audio->tx_agc_cfg.tx_agc_param_mask =
393 (1 << AUDPREPROC_CMD_TX_AGC_PARAM_MASK_TX_AGC_ENA_FLAG);
394 audio->tx_agc_cfg.tx_agc_enable_flag =
395 AUDPREPROC_CMD_TX_AGC_ENA_FLAG_DIS;
396 }
397 cmd = audio->tx_agc_cfg;
398
399 return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
400}
401
402static int audio_enable_tx_agc(struct audio_in *audio, int enable)
403{
404 if (audio->tx_agc_enable != enable) {
405 audio->tx_agc_enable = enable;
406 if (audio->running)
407 audio_dsp_set_tx_agc(audio);
408 }
409 return 0;
410}
411
412static int audio_dsp_set_ns(struct audio_in *audio)
413{
414 audpreproc_cmd_cfg_ns_params cmd;
415
416 memset(&cmd, 0, sizeof(cmd));
417
418 audio->ns_cfg.cmd_id = AUDPREPROC_CMD_CFG_NS_PARAMS;
419
420 if (audio->ns_enable) {
421 /* cmd.ec_mode_new is fixed as 0x0064 when enable
422 * from sample code */
423 audio->ns_cfg.ec_mode_new =
424 AUDPREPROC_CMD_EC_MODE_NEW_NS_ENA |
425 AUDPREPROC_CMD_EC_MODE_NEW_HB_ENA |
426 AUDPREPROC_CMD_EC_MODE_NEW_VA_ENA;
427 } else {
428 audio->ns_cfg.ec_mode_new =
429 AUDPREPROC_CMD_EC_MODE_NEW_NLMS_DIS |
430 AUDPREPROC_CMD_EC_MODE_NEW_DES_DIS |
431 AUDPREPROC_CMD_EC_MODE_NEW_NS_DIS |
432 AUDPREPROC_CMD_EC_MODE_NEW_CNI_DIS |
433 AUDPREPROC_CMD_EC_MODE_NEW_NLES_DIS |
434 AUDPREPROC_CMD_EC_MODE_NEW_HB_DIS |
435 AUDPREPROC_CMD_EC_MODE_NEW_VA_DIS |
436 AUDPREPROC_CMD_EC_MODE_NEW_PCD_DIS |
437 AUDPREPROC_CMD_EC_MODE_NEW_FEHI_DIS |
438 AUDPREPROC_CMD_EC_MODE_NEW_NEHI_DIS |
439 AUDPREPROC_CMD_EC_MODE_NEW_NLPP_DIS |
440 AUDPREPROC_CMD_EC_MODE_NEW_FNE_DIS |
441 AUDPREPROC_CMD_EC_MODE_NEW_PRENLMS_DIS;
442 }
443 cmd = audio->ns_cfg;
444
445 return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
446}
447
448static int audio_enable_ns(struct audio_in *audio, int enable)
449{
450 if (audio->ns_enable != enable) {
451 audio->ns_enable = enable;
452 if (audio->running)
453 audio_dsp_set_ns(audio);
454 }
455 return 0;
456}
457
458static int audio_dsp_set_iir(struct audio_in *audio)
459{
460 audpreproc_cmd_cfg_iir_tuning_filter_params cmd;
461
462 memset(&cmd, 0, sizeof(cmd));
463
464 audio->iir_cfg.cmd_id = AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS;
465
466 if (audio->iir_enable)
467 /* cmd.active_flag is 0xFFFF from sample code but 0x0001 here */
468 audio->iir_cfg.active_flag = AUDPREPROC_CMD_IIR_ACTIVE_FLAG_ENA;
469 else
470 audio->iir_cfg.active_flag = AUDPREPROC_CMD_IIR_ACTIVE_FLAG_DIS;
471
472 cmd = audio->iir_cfg;
473
474 return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
475}
476
477static int audio_enable_iir(struct audio_in *audio, int enable)
478{
479 if (audio->iir_enable != enable) {
480 audio->iir_enable = enable;
481 if (audio->running)
482 audio_dsp_set_iir(audio);
483 }
484 return 0;
485}
486
487static int audio_in_dsp_enable(struct audio_in *audio, int enable)
488{
489 audrec_cmd_cfg cmd;
490
491 memset(&cmd, 0, sizeof(cmd));
492 cmd.cmd_id = AUDREC_CMD_CFG;
493 cmd.type_0 = enable ? AUDREC_CMD_TYPE_0_ENA : AUDREC_CMD_TYPE_0_DIS;
494 cmd.type_0 |= (AUDREC_CMD_TYPE_0_UPDATE | audio->type);
495 cmd.type_1 = 0;
496
497 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
498}
499
500static int audio_in_encoder_config(struct audio_in *audio)
501{
502 audrec_cmd_arec0param_cfg cmd;
503 uint16_t *data = (void *) audio->data;
504 unsigned n;
505
506 memset(&cmd, 0, sizeof(cmd));
507 cmd.cmd_id = AUDREC_CMD_AREC0PARAM_CFG;
508 cmd.ptr_to_extpkt_buffer_msw = audio->phys >> 16;
509 cmd.ptr_to_extpkt_buffer_lsw = audio->phys;
510 cmd.buf_len = FRAME_NUM; /* Both WAV and AAC use 8 frames */
511 cmd.samp_rate_index = audio->samp_rate_index;
512 cmd.stereo_mode = audio->channel_mode; /* 0 for mono, 1 for stereo */
513
514 /* cmd.rec_quality is based on user set bit rate / sample rate /
515 * channel
516 */
517 cmd.rec_quality = audio->record_quality;
518
519 /* prepare buffer pointers:
520 * Mono: 1024 samples + 4 halfword header
521 * Stereo: 2048 samples + 4 halfword header
522 * AAC
523 * Mono/Stere: 768 + 4 halfword header
524 */
525 for (n = 0; n < FRAME_NUM; n++) {
526 audio->in[n].data = data + 4;
527 if (audio->type == AUDREC_CMD_TYPE_0_INDEX_WAV)
528 data += (4 + (audio->channel_mode ? 2048 : 1024));
529 else if (audio->type == AUDREC_CMD_TYPE_0_INDEX_AAC)
530 data += (4 + 768);
531 }
532
533 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
534}
535
536static int audio_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt)
537{
538 audrec_cmd_packet_ext_ptr cmd;
539
540 memset(&cmd, 0, sizeof(cmd));
541 cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
542 /* Both WAV and AAC use AUDREC_CMD_TYPE_0 */
543 cmd.type = AUDREC_CMD_TYPE_0;
544 cmd.curr_rec_count_msw = read_cnt >> 16;
545 cmd.curr_rec_count_lsw = read_cnt;
546
547 return audio_send_queue_recbs(audio, &cmd, sizeof(cmd));
548}
549
550/* ------------------- device --------------------- */
551
552static void audio_flush(struct audio_in *audio)
553{
554 int i;
555
556 audio->dsp_cnt = 0;
557 audio->in_head = 0;
558 audio->in_tail = 0;
559 audio->in_count = 0;
560 for (i = 0; i < FRAME_NUM; i++) {
561 audio->in[i].size = 0;
562 audio->in[i].read = 0;
563 }
564}
565
566static long audio_in_ioctl(struct file *file,
567 unsigned int cmd, unsigned long arg)
568{
569 struct audio_in *audio = file->private_data;
570 int rc;
571
572 if (cmd == AUDIO_GET_STATS) {
573 struct msm_audio_stats stats;
574 stats.byte_count = atomic_read(&audio->in_bytes);
575 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
576 return -EFAULT;
577 return 0;
578 }
579
580 mutex_lock(&audio->lock);
581 switch (cmd) {
582 case AUDIO_START:
583 rc = audio_in_enable(audio);
584 break;
585 case AUDIO_STOP:
586 rc = audio_in_disable(audio);
587 audio->stopped = 1;
588 break;
589 case AUDIO_FLUSH:
590 if (audio->stopped) {
591 /* Make sure we're stopped and we wake any threads
592 * that might be blocked holding the read_lock.
593 * While audio->stopped read threads will always
594 * exit immediately.
595 */
596 wake_up(&audio->wait);
597 mutex_lock(&audio->read_lock);
598 audio_flush(audio);
599 mutex_unlock(&audio->read_lock);
600 }
601 case AUDIO_SET_CONFIG: {
602 struct msm_audio_config cfg;
603 /* The below code is to make mutual exclusive between
604 * AUDIO_SET_CONFIG and AUDIO_SET_STREAM_CONFIG.
605 * Allow any one IOCTL.
606 */
607 if (audio->buffer_cfg_ioctl == AUDIO_SET_STREAM_CONFIG) {
608 rc = -EINVAL;
609 break;
610 }
611 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
612 rc = -EFAULT;
613 break;
614 }
615 if (cfg.channel_count == 1) {
616 cfg.channel_count = AUDREC_CMD_STEREO_MODE_MONO;
617 } else if (cfg.channel_count == 2) {
618 cfg.channel_count = AUDREC_CMD_STEREO_MODE_STEREO;
619 } else {
620 rc = -EINVAL;
621 break;
622 }
623
624 if (cfg.type == 0) {
625 cfg.type = AUDREC_CMD_TYPE_0_INDEX_WAV;
626 } else if (cfg.type == 1) {
627 cfg.type = AUDREC_CMD_TYPE_0_INDEX_AAC;
628 } else {
629 rc = -EINVAL;
630 break;
631 }
632 audio->samp_rate = convert_samp_rate(cfg.sample_rate);
633 audio->samp_rate_index =
634 convert_dsp_samp_index(cfg.sample_rate);
635 audio->channel_mode = cfg.channel_count;
636 audio->buffer_size =
637 audio->channel_mode ? STEREO_DATA_SIZE
638 : MONO_DATA_SIZE;
639 audio->type = cfg.type;
640 audio->buffer_cfg_ioctl = AUDIO_SET_CONFIG;
641 rc = 0;
642 break;
643 }
644 case AUDIO_GET_CONFIG: {
645 struct msm_audio_config cfg;
646 cfg.buffer_size = audio->buffer_size;
647 cfg.buffer_count = FRAME_NUM;
648 cfg.sample_rate = convert_samp_index(audio->samp_rate);
649 if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO)
650 cfg.channel_count = 1;
651 else
652 cfg.channel_count = 2;
653 if (audio->type == AUDREC_CMD_TYPE_0_INDEX_WAV)
654 cfg.type = 0;
655 else
656 cfg.type = 1;
657 cfg.unused[0] = 0;
658 cfg.unused[1] = 0;
659 cfg.unused[2] = 0;
660 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
661 rc = -EFAULT;
662 else
663 rc = 0;
664 break;
665 }
666 case AUDIO_GET_STREAM_CONFIG: {
667 struct msm_audio_stream_config cfg;
668 cfg.buffer_size = audio->buffer_size;
669 cfg.buffer_count = FRAME_NUM;
670 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
671 rc = -EFAULT;
672 else
673 rc = 0;
674 break;
675 }
676 case AUDIO_SET_STREAM_CONFIG: {
677 struct msm_audio_stream_config cfg;
678 /* The below code is to make mutual exclusive between
679 * AUDIO_SET_CONFIG and AUDIO_SET_STREAM_CONFIG.
680 * Allow any one IOCTL.
681 */
682 if (audio->buffer_cfg_ioctl == AUDIO_SET_CONFIG) {
683 rc = -EINVAL;
684 break;
685 }
686 if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
687 rc = -EFAULT;
688 break;
689 } else
690 rc = 0;
691 audio->buffer_size = cfg.buffer_size;
692 /* The IOCTL is only of AAC, set the encoder as AAC */
693 audio->type = 1;
694 audio->buffer_cfg_ioctl = AUDIO_SET_STREAM_CONFIG;
695 break;
696 }
697 case AUDIO_GET_AAC_ENC_CONFIG: {
698 struct msm_audio_aac_enc_config cfg;
699 if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO)
700 cfg.channels = 1;
701 else
702 cfg.channels = 2;
703 cfg.sample_rate = convert_samp_index(audio->samp_rate);
704 cfg.bit_rate = audio->bit_rate;
705 cfg.stream_format = AUDIO_AAC_FORMAT_RAW;
706 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
707 rc = -EFAULT;
708 else
709 rc = 0;
710 break;
711 }
712 case AUDIO_SET_AAC_ENC_CONFIG: {
713 struct msm_audio_aac_enc_config cfg;
714 unsigned int record_quality;
715 if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
716 rc = -EFAULT;
717 break;
718 }
719 if (cfg.stream_format != AUDIO_AAC_FORMAT_RAW) {
720 MM_ERR("unsupported AAC format\n");
721 rc = -EINVAL;
722 break;
723 }
724 record_quality = bitrate_to_record_quality(cfg.sample_rate,
725 cfg.channels, cfg.bit_rate);
726 /* Range of Record Quality Supported by DSP, Q12 format */
727 if ((record_quality < 0x800) || (record_quality > 0x4000)) {
728 MM_ERR("Unsupported bit rate \n");
729 rc = -EINVAL;
730 break;
731 }
732 if (cfg.channels == 1) {
733 cfg.channels = AUDREC_CMD_STEREO_MODE_MONO;
734 } else if (cfg.channels == 2) {
735 cfg.channels = AUDREC_CMD_STEREO_MODE_STEREO;
736 } else {
737 rc = -EINVAL;
738 break;
739 }
740 audio->samp_rate = convert_samp_rate(cfg.sample_rate);
741 audio->samp_rate_index =
742 convert_dsp_samp_index(cfg.sample_rate);
743 audio->channel_mode = cfg.channels;
744 audio->bit_rate = cfg.bit_rate;
745 audio->record_quality = record_quality;
746 MM_DBG(" Record Quality = 0x%8x \n", audio->record_quality);
747 rc = 0;
748 break;
749 }
750 default:
751 rc = -EINVAL;
752 }
753 mutex_unlock(&audio->lock);
754 return rc;
755}
756
757static ssize_t audio_in_read(struct file *file,
758 char __user *buf,
759 size_t count, loff_t *pos)
760{
761 struct audio_in *audio = file->private_data;
762 unsigned long flags;
763 const char __user *start = buf;
764 void *data;
765 uint32_t index;
766 uint32_t size;
767 int rc = 0;
768
769 mutex_lock(&audio->read_lock);
770 while (count > 0) {
771 rc = wait_event_interruptible(
772 audio->wait, (audio->in_count > 0) || audio->stopped);
773 if (rc < 0)
774 break;
775
776 if (audio->stopped && !audio->in_count) {
777 rc = 0;/* End of File */
778 break;
779 }
780
781 index = audio->in_tail;
782 data = (uint8_t *) audio->in[index].data;
783 size = audio->in[index].size;
784 if (count >= size) {
785 /* order the reads on the buffer */
786 dma_coherent_post_ops();
787 if (copy_to_user(buf, data, size)) {
788 rc = -EFAULT;
789 break;
790 }
791 spin_lock_irqsave(&audio->dsp_lock, flags);
792 if (index != audio->in_tail) {
793 /* overrun -- data is invalid and we need to retry */
794 spin_unlock_irqrestore(&audio->dsp_lock, flags);
795 continue;
796 }
797 audio->in[index].size = 0;
798 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
799 audio->in_count--;
800 spin_unlock_irqrestore(&audio->dsp_lock, flags);
801 count -= size;
802 buf += size;
803 } else {
804 MM_ERR("short read\n");
805 break;
806 }
807 if (audio->type == AUDREC_CMD_TYPE_0_INDEX_AAC)
808 break; /* AAC only read one frame */
809 }
810 mutex_unlock(&audio->read_lock);
811
812 if (buf > start)
813 return buf - start;
814
815 return rc;
816}
817
818static ssize_t audio_in_write(struct file *file,
819 const char __user *buf,
820 size_t count, loff_t *pos)
821{
822 return -EINVAL;
823}
824
825static int audio_in_release(struct inode *inode, struct file *file)
826{
827 struct audio_in *audio = file->private_data;
828
829 mutex_lock(&audio->lock);
830 audio_in_disable(audio);
831 audio_flush(audio);
832 msm_adsp_put(audio->audrec);
833 msm_adsp_put(audio->audpre);
834 audio->audrec = NULL;
835 audio->audpre = NULL;
836 audio->opened = 0;
837 mutex_unlock(&audio->lock);
838 return 0;
839}
840
841struct audio_in the_audio_in;
842
843static int audio_in_open(struct inode *inode, struct file *file)
844{
845 struct audio_in *audio = &the_audio_in;
846 int rc;
847
848 mutex_lock(&audio->lock);
849 if (audio->opened) {
850 rc = -EBUSY;
851 goto done;
852 }
853
854 /* Settings will be re-config at AUDIO_SET_CONFIG,
855 * but at least we need to have initial config
856 */
857 audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_11025;
858 audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_11025;
859 audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
860 audio->buffer_size = MONO_DATA_SIZE;
861 audio->type = AUDREC_CMD_TYPE_0_INDEX_WAV;
862
863 /* For AAC, bit rate hard coded, default settings is
864 * sample rate (11025) x channel count (1) x recording quality (1.75)
865 * = 19293 bps */
866 audio->bit_rate = 19293;
867 audio->record_quality = 0x1c00;
868
869 rc = audmgr_open(&audio->audmgr);
870 if (rc)
871 goto done;
872 rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
873 &audpre_adsp_ops, audio);
874 if (rc)
875 goto done;
876 rc = msm_adsp_get("AUDRECTASK", &audio->audrec,
877 &audrec_adsp_ops, audio);
878 if (rc)
879 goto done;
880
881 audio->dsp_cnt = 0;
882 audio->stopped = 0;
883 audio->buffer_cfg_ioctl = 0; /* No valid ioctl set */
884
885 audio_flush(audio);
886
887 file->private_data = audio;
888 audio->opened = 1;
889 rc = 0;
890done:
891 mutex_unlock(&audio->lock);
892 return rc;
893}
894
895static long audpre_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
896{
897 struct audio_in *audio = file->private_data;
898 int rc = 0, enable;
899 uint16_t enable_mask;
900
901 mutex_lock(&audio->lock);
902 switch (cmd) {
903 case AUDIO_ENABLE_AUDPRE:
904 if (copy_from_user(&enable_mask, (void *) arg,
905 sizeof(enable_mask))) {
906 rc = -EFAULT;
907 break;
908 }
909
910 enable = (enable_mask & AGC_ENABLE) ? 1 : 0;
911 audio_enable_tx_agc(audio, enable);
912 enable = (enable_mask & NS_ENABLE) ? 1 : 0;
913 audio_enable_ns(audio, enable);
914 enable = (enable_mask & TX_IIR_ENABLE) ? 1 : 0;
915 audio_enable_iir(audio, enable);
916 break;
917
918 case AUDIO_SET_AGC:
919 if (copy_from_user(&audio->tx_agc_cfg, (void *) arg,
920 sizeof(audio->tx_agc_cfg)))
921 rc = -EFAULT;
922 break;
923
924 case AUDIO_SET_NS:
925 if (copy_from_user(&audio->ns_cfg, (void *) arg,
926 sizeof(audio->ns_cfg)))
927 rc = -EFAULT;
928 break;
929
930 case AUDIO_SET_TX_IIR:
931 if (copy_from_user(&audio->iir_cfg, (void *) arg,
932 sizeof(audio->iir_cfg)))
933 rc = -EFAULT;
934 break;
935
936 default:
937 rc = -EINVAL;
938 }
939
940 mutex_unlock(&audio->lock);
941 return rc;
942}
943
944static int audpre_open(struct inode *inode, struct file *file)
945{
946 struct audio_in *audio = &the_audio_in;
947
948 file->private_data = audio;
949
950 return 0;
951}
952
953static struct file_operations audio_fops = {
954 .owner = THIS_MODULE,
955 .open = audio_in_open,
956 .release = audio_in_release,
957 .read = audio_in_read,
958 .write = audio_in_write,
959 .unlocked_ioctl = audio_in_ioctl,
960};
961
962struct miscdevice audio_in_misc = {
963 .minor = MISC_DYNAMIC_MINOR,
964 .name = "msm_pcm_in",
965 .fops = &audio_fops,
966};
967
968static const struct file_operations audpre_fops = {
969 .owner = THIS_MODULE,
970 .open = audpre_open,
971 .unlocked_ioctl = audpre_ioctl,
972};
973
974struct miscdevice audpre_misc = {
975 .minor = MISC_DYNAMIC_MINOR,
976 .name = "msm_preproc_ctl",
977 .fops = &audpre_fops,
978};
979
980static int __init audio_in_init(void)
981{
982 the_audio_in.data = dma_alloc_coherent(NULL, DMASZ,
983 &the_audio_in.phys, GFP_KERNEL);
984 if (!the_audio_in.data) {
985 MM_ERR("Unable to allocate DMA buffer\n");
986 return -ENOMEM;
987 }
988
989 mutex_init(&the_audio_in.lock);
990 mutex_init(&the_audio_in.read_lock);
991 spin_lock_init(&the_audio_in.dsp_lock);
992 init_waitqueue_head(&the_audio_in.wait);
993 return misc_register(&audio_in_misc) || misc_register(&audpre_misc);
994}
995
996device_initcall(audio_in_init);