blob: 8d644f0a581ce13b00a00191187498f1cded05a7 [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * sbc/pcm audio input driver
4 * Based on the pcm input driver in arch/arm/mach-msm/qdsp5v2/audio_pcm_in.c
5 *
6 * Copyright (C) 2008 HTC Corporation
7 * Copyright (C) 2008 Google, Inc.
Sidipotu Ashok823c1532012-10-04 15:20:24 +05308 * Copyright (c) 2012 The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07009 *
10 * All source code in this file is licensed under the following license except
11 * where indicated.
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License version 2 as published
15 * by the Free Software Foundation.
16 *
17 * This software is licensed under the terms of the GNU General Public
18 * License version 2, as published by the Free Software Foundation, and
19 * may be copied, distributed, and modified under those terms.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 */
Santosh Mardifdc227a2011-07-11 17:20:34 +053027#include <asm/atomic.h>
28#include <asm/ioctls.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070029#include <linux/module.h>
30#include <linux/fs.h>
31#include <linux/miscdevice.h>
32#include <linux/uaccess.h>
33#include <linux/sched.h>
34#include <linux/wait.h>
35#include <linux/dma-mapping.h>
36#include <linux/msm_audio.h>
37#include <linux/msm_audio_sbc.h>
Sidipotu Ashok823c1532012-10-04 15:20:24 +053038#include <linux/msm_ion.h>
Santosh Mardifdc227a2011-07-11 17:20:34 +053039#include <linux/memory_alloc.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040
Santosh Mardifdc227a2011-07-11 17:20:34 +053041#include <mach/iommu.h>
42#include <mach/iommu_domains.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043#include <mach/msm_adsp.h>
Santosh Mardifdc227a2011-07-11 17:20:34 +053044#include <mach/msm_memtypes.h>
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +053045#include <mach/socinfo.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046#include <mach/qdsp5v2/qdsp5audreccmdi.h>
47#include <mach/qdsp5v2/qdsp5audrecmsg.h>
48#include <mach/qdsp5v2/audpreproc.h>
49#include <mach/qdsp5v2/audio_dev_ctl.h>
50#include <mach/debug_mm.h>
51
52/* FRAME_NUM must be a power of two */
53#define FRAME_NUM (8)
54#define FRAME_SIZE (2052 * 2)
55#define FRAME_SIZE_SBC (768 * 2)
56#define MONO_DATA_SIZE (2048)
57#define STEREO_DATA_SIZE (MONO_DATA_SIZE * 2)
58#define DMASZ (FRAME_SIZE * FRAME_NUM)
59
60struct buffer {
61 void *data;
62 uint32_t size;
63 uint32_t read;
64 uint32_t addr;
65 uint32_t frame_num;
66 uint32_t frame_len;
67};
68
69struct audio_a2dp_in {
70 struct buffer in[FRAME_NUM];
71
72 spinlock_t dsp_lock;
73
74 atomic_t in_bytes;
75 atomic_t in_samples;
76
77 struct mutex lock;
78 struct mutex read_lock;
79 wait_queue_head_t wait;
80 wait_queue_head_t wait_enable;
81
82 struct msm_adsp_module *audrec;
83
84 struct audrec_session_info session_info; /*audrec session info*/
85
86 /* configuration to use on next enable */
87 uint32_t samp_rate;
88 uint32_t channel_mode;
89 uint32_t buffer_size; /* 2048 for mono, 4096 for stereo */
90 uint32_t enc_type;
91 struct msm_audio_sbc_enc_config cfg;
92
93 uint32_t dsp_cnt;
94 uint32_t in_head; /* next buffer dsp will write */
95 uint32_t in_tail; /* next buffer read() will read */
96 uint32_t in_count; /* number of buffers available to read() */
97 uint32_t mode;
98
99 const char *module_name;
100 unsigned queue_ids;
101 uint16_t enc_id; /* Session Id */
102
103 uint16_t source; /* Encoding source bit mask */
104 uint32_t device_events; /* device events interested in */
105 uint32_t dev_cnt;
106 spinlock_t dev_lock;
107
108 /* data allocated for various buffers */
109 char *data;
110 dma_addr_t phys;
Laura Abbott61399692012-04-30 14:25:46 -0700111 void *msm_map;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700112
113 int opened;
114 int enabled;
115 int running;
116 int stopped; /* set when stopped, cleared on flush */
117 int abort; /* set when error, like sample rate mismatch */
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +0530118 char *build_id;
Sidipotu Ashok823c1532012-10-04 15:20:24 +0530119 struct ion_client *client;
120 struct ion_handle *output_buff_handle;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700121};
122
123static struct audio_a2dp_in the_audio_a2dp_in;
124
125struct wav_frame {
126 uint16_t frame_count_lsw;
127 uint16_t frame_count_msw;
128 uint16_t frame_length;
129 uint16_t erased_a2dp;
130 unsigned char raw_bitstream[]; /* samples */
131};
132
133struct sbc_frame {
134 uint16_t bit_rate_msw;
135 uint16_t bit_rate_lsw;
136 uint16_t frame_length;
137 uint16_t frame_num;
138 unsigned char raw_bitstream[]; /* samples */
139};
140
141struct audio_frame {
142 union {
143 struct wav_frame wav;
144 struct sbc_frame sbc;
145 } a2dp;
146} __attribute__((packed));
147
148/* Audrec Queue command sent macro's */
149#define audrec_send_bitstreamqueue(audio, cmd, len) \
150 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
151 cmd, len)
152
153#define audrec_send_audrecqueue(audio, cmd, len) \
154 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
155 cmd, len)
156
157/* DSP command send functions */
158static int auda2dp_in_enc_config(struct audio_a2dp_in *audio, int enable);
159static int auda2dp_in_param_config(struct audio_a2dp_in *audio);
160static int auda2dp_in_mem_config(struct audio_a2dp_in *audio);
161static int auda2dp_in_record_config(struct audio_a2dp_in *audio, int enable);
162static int auda2dp_dsp_read_buffer(struct audio_a2dp_in *audio,
163 uint32_t read_cnt);
164
165static void auda2dp_in_get_dsp_frames(struct audio_a2dp_in *audio);
166
167static void auda2dp_in_flush(struct audio_a2dp_in *audio);
168
169static void a2dp_in_listener(u32 evt_id, union auddev_evt_data *evt_payload,
170 void *private_data)
171{
172 struct audio_a2dp_in *audio = (struct audio_a2dp_in *) private_data;
173 unsigned long flags;
174
175 MM_DBG("evt_id = 0x%8x\n", evt_id);
176 switch (evt_id) {
177 case AUDDEV_EVT_DEV_RDY: {
178 MM_DBG("AUDDEV_EVT_DEV_RDY\n");
179 spin_lock_irqsave(&audio->dev_lock, flags);
180 audio->dev_cnt++;
181 audio->source |= (0x1 << evt_payload->routing_id);
182 spin_unlock_irqrestore(&audio->dev_lock, flags);
183
184 if ((audio->running == 1) && (audio->enabled == 1))
185 auda2dp_in_record_config(audio, 1);
186
187 break;
188 }
189 case AUDDEV_EVT_DEV_RLS: {
190 MM_DBG("AUDDEV_EVT_DEV_RLS\n");
191 spin_lock_irqsave(&audio->dev_lock, flags);
192 audio->dev_cnt--;
193 audio->source &= ~(0x1 << evt_payload->routing_id);
194 spin_unlock_irqrestore(&audio->dev_lock, flags);
195
196 if (!audio->running || !audio->enabled)
197 break;
198
199 /* Turn of as per source */
200 if (audio->source)
201 auda2dp_in_record_config(audio, 1);
202 else
203 /* Turn off all */
204 auda2dp_in_record_config(audio, 0);
205
206 break;
207 }
208 case AUDDEV_EVT_FREQ_CHG: {
209 MM_DBG("Encoder Driver got sample rate change event\n");
210 MM_DBG("sample rate %d\n", evt_payload->freq_info.sample_rate);
211 MM_DBG("dev_type %d\n", evt_payload->freq_info.dev_type);
212 MM_DBG("acdb_dev_id %d\n", evt_payload->freq_info.acdb_dev_id);
213 if (audio->running == 1) {
214 /* Stop Recording sample rate does not match
215 with device sample rate */
216 if (evt_payload->freq_info.sample_rate !=
217 audio->samp_rate) {
218 auda2dp_in_record_config(audio, 0);
219 audio->abort = 1;
220 wake_up(&audio->wait);
221 }
222 }
223 break;
224 }
225 default:
226 MM_ERR("wrong event %d\n", evt_id);
227 break;
228 }
229}
230
231/* ------------------- dsp preproc event handler--------------------- */
232static void audpreproc_dsp_event(void *data, unsigned id, void *msg)
233{
234 struct audio_a2dp_in *audio = data;
235
236 switch (id) {
237 case AUDPREPROC_ERROR_MSG: {
238 struct audpreproc_err_msg *err_msg = msg;
239
240 MM_ERR("ERROR_MSG: stream id %d err idx %d\n",
241 err_msg->stream_id, err_msg->aud_preproc_err_idx);
242 /* Error case */
243 wake_up(&audio->wait_enable);
244 break;
245 }
246 case AUDPREPROC_CMD_CFG_DONE_MSG: {
247 MM_DBG("CMD_CFG_DONE_MSG \n");
248 break;
249 }
250 case AUDPREPROC_CMD_ENC_CFG_DONE_MSG: {
251 struct audpreproc_cmd_enc_cfg_done_msg *enc_cfg_msg = msg;
252
253 MM_DBG("CMD_ENC_CFG_DONE_MSG: stream id %d enc type \
254 0x%8x\n", enc_cfg_msg->stream_id,
255 enc_cfg_msg->rec_enc_type);
256 /* Encoder enable success */
257 if (enc_cfg_msg->rec_enc_type & ENCODE_ENABLE)
258 auda2dp_in_param_config(audio);
259 else { /* Encoder disable success */
260 audio->running = 0;
261 auda2dp_in_record_config(audio, 0);
262 }
263 break;
264 }
265 case AUDPREPROC_CMD_ENC_PARAM_CFG_DONE_MSG: {
266 MM_DBG("CMD_ENC_PARAM_CFG_DONE_MSG \n");
267 auda2dp_in_mem_config(audio);
268 break;
269 }
270 case AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG: {
271 MM_DBG("AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG \n");
272 wake_up(&audio->wait_enable);
273 break;
274 }
275 default:
276 MM_ERR("Unknown Event id %d\n", id);
277 }
278}
279
280/* ------------------- dsp audrec event handler--------------------- */
281static void audrec_dsp_event(void *data, unsigned id, size_t len,
282 void (*getevent)(void *ptr, size_t len))
283{
284 struct audio_a2dp_in *audio = data;
285
286 switch (id) {
287 case AUDREC_CMD_MEM_CFG_DONE_MSG: {
288 MM_DBG("CMD_MEM_CFG_DONE MSG DONE\n");
289 audio->running = 1;
290 if (audio->dev_cnt > 0)
291 auda2dp_in_record_config(audio, 1);
292 break;
293 }
294 case AUDREC_FATAL_ERR_MSG: {
295 struct audrec_fatal_err_msg fatal_err_msg;
296
297 getevent(&fatal_err_msg, AUDREC_FATAL_ERR_MSG_LEN);
298 MM_ERR("FATAL_ERR_MSG: err id %d\n",
299 fatal_err_msg.audrec_err_id);
300 /* Error stop the encoder */
301 audio->stopped = 1;
302 wake_up(&audio->wait);
303 break;
304 }
305 case AUDREC_UP_PACKET_READY_MSG: {
306 struct audrec_up_pkt_ready_msg pkt_ready_msg;
307
308 getevent(&pkt_ready_msg, AUDREC_UP_PACKET_READY_MSG_LEN);
309 MM_DBG("UP_PACKET_READY_MSG: write cnt lsw %d \
310 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
311 pkt_ready_msg.audrec_packet_write_cnt_lsw, \
312 pkt_ready_msg.audrec_packet_write_cnt_msw, \
313 pkt_ready_msg.audrec_up_prev_read_cnt_lsw, \
314 pkt_ready_msg.audrec_up_prev_read_cnt_msw);
315
316 auda2dp_in_get_dsp_frames(audio);
317 break;
318 }
319 case ADSP_MESSAGE_ID: {
320 MM_DBG("Received ADSP event: module audrectask\n");
321 break;
322 }
323 default:
324 MM_ERR("Unknown Event id %d\n", id);
325 }
326}
327
328static void auda2dp_in_get_dsp_frames(struct audio_a2dp_in *audio)
329{
330 struct audio_frame *frame;
331 uint32_t index;
332 unsigned long flags;
333
334 index = audio->in_head;
335
336 frame = (void *) (((char *)audio->in[index].data) - \
337 sizeof(*frame));
338
339 spin_lock_irqsave(&audio->dsp_lock, flags);
340 if (audio->enc_type == ENC_TYPE_WAV)
341 audio->in[index].size = frame->a2dp.wav.frame_length;
342 else if (audio->enc_type == ENC_TYPE_SBC) {
343 audio->in[index].size = frame->a2dp.sbc.frame_length *
344 frame->a2dp.sbc.frame_num;
345 audio->in[index].frame_num = frame->a2dp.sbc.frame_num;
346 audio->in[index].frame_len = frame->a2dp.sbc.frame_length;
347 }
348
349 /* statistics of read */
350 atomic_add(audio->in[index].size, &audio->in_bytes);
351 atomic_add(1, &audio->in_samples);
352
353 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
354
355 /* If overflow, move the tail index foward. */
356 if (audio->in_head == audio->in_tail)
357 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
358 else
359 audio->in_count++;
360
361 auda2dp_dsp_read_buffer(audio, audio->dsp_cnt++);
362 spin_unlock_irqrestore(&audio->dsp_lock, flags);
363 wake_up(&audio->wait);
364}
365
366static struct msm_adsp_ops audrec_adsp_ops = {
367 .event = audrec_dsp_event,
368};
369
370static int auda2dp_in_enc_config(struct audio_a2dp_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;
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +0530377 } else {
378 cmd.cmd_id = AUDPREPROC_AUDREC_CMD_ENC_CFG;
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +0530379 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700380 cmd.stream_id = audio->enc_id;
381
382 if (enable)
383 cmd.audrec_enc_type = audio->enc_type | ENCODE_ENABLE;
384 else
385 cmd.audrec_enc_type &= ~(ENCODE_ENABLE);
386
387 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
388}
389
390static int auda2dp_in_param_config(struct audio_a2dp_in *audio)
391{
392 if (audio->enc_type == ENC_TYPE_WAV) {
393 struct audpreproc_audrec_cmd_parm_cfg_wav cmd;
394
395 memset(&cmd, 0, sizeof(cmd));
396 cmd.common.cmd_id = AUDPREPROC_AUDREC_CMD_PARAM_CFG;
397 cmd.common.stream_id = audio->enc_id;
398
399 cmd.aud_rec_samplerate_idx = audio->samp_rate;
400 cmd.aud_rec_stereo_mode = audio->channel_mode;
401 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
402 } else if (audio->enc_type == ENC_TYPE_SBC) {
403 struct audpreproc_audrec_cmd_parm_cfg_sbc cmd;
404
405 memset(&cmd, 0, sizeof(cmd));
406 cmd.common.cmd_id = AUDPREPROC_AUDREC_CMD_PARAM_CFG;
407 cmd.common.stream_id = audio->enc_id;
408 cmd.aud_rec_sbc_enc_param =
409 (audio->cfg.number_of_blocks <<
410 AUDREC_SBC_ENC_PARAM_NUM_SUB_BLOCKS_MASK) |
411 (audio->cfg.number_of_subbands <<
412 AUDREC_SBC_ENC_PARAM_NUM_SUB_BANDS_MASK) |
413 (audio->cfg.mode <<
414 AUDREC_SBC_ENC_PARAM_MODE_MASK) |
415 (audio->cfg.bit_allocation <<
416 AUDREC_SBC_ENC_PARAM_BIT_ALLOC_MASK);
417 cmd.aud_rec_sbc_bit_rate_msw =
418 (audio->cfg.bit_rate & 0xFFFF0000) >> 16;
419 cmd.aud_rec_sbc_bit_rate_lsw =
420 (audio->cfg.bit_rate & 0xFFFF);
421 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
422 }
423 return 0;
424}
425
426/* To Do: msm_snddev_route_enc(audio->enc_id); */
427static int auda2dp_in_record_config(struct audio_a2dp_in *audio, int enable)
428{
429 struct audpreproc_afe_cmd_audio_record_cfg cmd;
430
431 memset(&cmd, 0, sizeof(cmd));
432 cmd.cmd_id = AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG;
433 cmd.stream_id = audio->enc_id;
434 if (enable)
435 cmd.destination_activity = AUDIO_RECORDING_TURN_ON;
436 else
437 cmd.destination_activity = AUDIO_RECORDING_TURN_OFF;
438
439 cmd.source_mix_mask = audio->source;
440 if (audio->enc_id == 2) {
441 if ((cmd.source_mix_mask &
442 INTERNAL_CODEC_TX_SOURCE_MIX_MASK) ||
443 (cmd.source_mix_mask & AUX_CODEC_TX_SOURCE_MIX_MASK) ||
444 (cmd.source_mix_mask & VOICE_UL_SOURCE_MIX_MASK) ||
445 (cmd.source_mix_mask & VOICE_DL_SOURCE_MIX_MASK)) {
446 cmd.pipe_id = SOURCE_PIPE_1;
447 }
448 if (cmd.source_mix_mask &
449 AUDPP_A2DP_PIPE_SOURCE_MIX_MASK)
450 cmd.pipe_id |= SOURCE_PIPE_0;
451 }
452 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
453}
454
455static int auda2dp_in_mem_config(struct audio_a2dp_in *audio)
456{
457 struct audrec_cmd_arecmem_cfg cmd;
458 uint16_t *data = (void *) audio->data;
459 int n;
460
461 memset(&cmd, 0, sizeof(cmd));
462 cmd.cmd_id = AUDREC_CMD_MEM_CFG_CMD;
463 cmd.audrec_up_pkt_intm_count = 1;
464 cmd.audrec_ext_pkt_start_addr_msw = audio->phys >> 16;
465 cmd.audrec_ext_pkt_start_addr_lsw = audio->phys;
466 cmd.audrec_ext_pkt_buf_number = FRAME_NUM;
467
468 /* prepare buffer pointers:
469 * Wav:
470 * Mono: 1024 samples + 4 halfword header
471 * Stereo: 2048 samples + 4 halfword header
472 * SBC:
473 * 768 + 4 halfword header
474 */
475 if (audio->enc_type == ENC_TYPE_SBC) {
476 for (n = 0; n < FRAME_NUM; n++) {
477 audio->in[n].data = data + 4;
478 data += (4 + (FRAME_SIZE_SBC/2));
479 MM_DBG("0x%8x\n", (int)(audio->in[n].data - 8));
480 }
481 } else if (audio->enc_type == ENC_TYPE_WAV) {
482 for (n = 0; n < FRAME_NUM; n++) {
483 audio->in[n].data = data + 4;
484 data += (4 + (audio->channel_mode ? 2048 : 1024));
485 MM_DBG("0x%8x\n", (int)(audio->in[n].data - 8));
486 }
487 }
488
489 return audrec_send_audrecqueue(audio, &cmd, sizeof(cmd));
490}
491
492static int auda2dp_dsp_read_buffer(struct audio_a2dp_in *audio,
493 uint32_t read_cnt)
494{
495 struct up_audrec_packet_ext_ptr cmd;
496
497 memset(&cmd, 0, sizeof(cmd));
498 cmd.cmd_id = UP_AUDREC_PACKET_EXT_PTR;
499 cmd.audrec_up_curr_read_count_msw = read_cnt >> 16;
500 cmd.audrec_up_curr_read_count_lsw = read_cnt;
501
502 return audrec_send_bitstreamqueue(audio, &cmd, sizeof(cmd));
503}
504
505/* must be called with audio->lock held */
506static int auda2dp_in_enable(struct audio_a2dp_in *audio)
507{
508 if (audio->enabled)
509 return 0;
510
511 if (audpreproc_enable(audio->enc_id, &audpreproc_dsp_event, audio)) {
512 MM_ERR("msm_adsp_enable(audpreproc) failed\n");
513 return -ENODEV;
514 }
515
516 if (msm_adsp_enable(audio->audrec)) {
517 MM_ERR("msm_adsp_enable(audrec) failed\n");
518 audpreproc_disable(audio->enc_id, audio);
519 return -ENODEV;
520 }
521 audio->enabled = 1;
522 auda2dp_in_enc_config(audio, 1);
523
524 return 0;
525}
526
527/* must be called with audio->lock held */
528static int auda2dp_in_disable(struct audio_a2dp_in *audio)
529{
530 if (audio->enabled) {
531 audio->enabled = 0;
532 auda2dp_in_enc_config(audio, 0);
533 wake_up(&audio->wait);
534 wait_event_interruptible_timeout(audio->wait_enable,
535 audio->running == 0, 1*HZ);
536 msm_adsp_disable(audio->audrec);
537 audpreproc_disable(audio->enc_id, audio);
538 }
539 return 0;
540}
541
542static void auda2dp_in_flush(struct audio_a2dp_in *audio)
543{
544 int i;
545
546 audio->dsp_cnt = 0;
547 audio->in_head = 0;
548 audio->in_tail = 0;
549 audio->in_count = 0;
550 for (i = 0; i < FRAME_NUM; i++) {
551 audio->in[i].size = 0;
552 audio->in[i].read = 0;
553 }
554 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
555 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
556 atomic_set(&audio->in_bytes, 0);
557 atomic_set(&audio->in_samples, 0);
558}
559
560/* ------------------- device --------------------- */
561static long auda2dp_in_ioctl(struct file *file,
562 unsigned int cmd, unsigned long arg)
563{
564 struct audio_a2dp_in *audio = file->private_data;
565 int rc = 0;
566
567 if (cmd == AUDIO_GET_STATS) {
568 struct msm_audio_stats stats;
569 stats.byte_count = atomic_read(&audio->in_bytes);
570 stats.sample_count = atomic_read(&audio->in_samples);
571 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
572 return -EFAULT;
573 return rc;
574 }
575
576 mutex_lock(&audio->lock);
577 switch (cmd) {
578 case AUDIO_START: {
579 uint32_t freq;
580 /* Poll at 48KHz always */
581 freq = 48000;
582 MM_DBG("AUDIO_START\n");
583 rc = msm_snddev_request_freq(&freq, audio->enc_id,
584 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
585 MM_DBG("sample rate configured %d sample rate requested %d\n",
586 freq, audio->samp_rate);
587 if (rc < 0) {
588 MM_DBG("sample rate can not be set, return code %d\n",\
589 rc);
590 msm_snddev_withdraw_freq(audio->enc_id,
591 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
592 MM_DBG("msm_snddev_withdraw_freq\n");
593 break;
594 }
595 /*update aurec session info in audpreproc layer*/
596 audio->session_info.session_id = audio->enc_id;
597 audio->session_info.sampling_freq = audio->samp_rate;
598 audpreproc_update_audrec_info(&audio->session_info);
599 rc = auda2dp_in_enable(audio);
600 if (!rc) {
601 rc =
602 wait_event_interruptible_timeout(audio->wait_enable,
603 audio->running != 0, 1*HZ);
604 MM_DBG("state %d rc = %d\n", audio->running, rc);
605
606 if (audio->running == 0) {
607 rc = -ENODEV;
608 msm_snddev_withdraw_freq(audio->enc_id,
609 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
610 MM_DBG("msm_snddev_withdraw_freq\n");
611 } else
612 rc = 0;
613 }
614 audio->stopped = 0;
615 break;
616 }
617 case AUDIO_STOP: {
618 /*reset the sampling frequency information at audpreproc layer*/
619 audio->session_info.sampling_freq = 0;
620 audpreproc_update_audrec_info(&audio->session_info);
621 rc = auda2dp_in_disable(audio);
622 rc = msm_snddev_withdraw_freq(audio->enc_id,
623 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
624 MM_DBG("msm_snddev_withdraw_freq\n");
625 audio->stopped = 1;
626 audio->abort = 0;
627 break;
628 }
629 case AUDIO_FLUSH: {
630 if (audio->stopped) {
631 /* Make sure we're stopped and we wake any threads
632 * that might be blocked holding the read_lock.
633 * While audio->stopped read threads will always
634 * exit immediately.
635 */
636 wake_up(&audio->wait);
637 mutex_lock(&audio->read_lock);
638 auda2dp_in_flush(audio);
639 mutex_unlock(&audio->read_lock);
640 }
641 break;
642 }
643 case AUDIO_SET_STREAM_CONFIG: {
644 struct msm_audio_stream_config cfg;
645 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
646 rc = -EFAULT;
647 break;
648 }
649 /* Allow only single frame */
650 if ((audio->enc_type == ENC_TYPE_SBC) &&
651 (cfg.buffer_size != FRAME_SIZE_SBC))
652 rc = -EINVAL;
653 else
654 audio->buffer_size = cfg.buffer_size;
655 break;
656 }
657 case AUDIO_GET_STREAM_CONFIG: {
658 struct msm_audio_stream_config cfg;
659 memset(&cfg, 0, sizeof(cfg));
660 if (audio->enc_type == ENC_TYPE_SBC)
661 cfg.buffer_size = FRAME_SIZE_SBC;
662 else
663 cfg.buffer_size = MONO_DATA_SIZE;
664 cfg.buffer_count = FRAME_NUM;
665 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
666 rc = -EFAULT;
667 break;
668 }
669 case AUDIO_SET_SBC_ENC_CONFIG: {
670 if (copy_from_user(&audio->cfg, (void *) arg,
671 sizeof(audio->cfg))) {
672 rc = -EFAULT;
673 break;
674 }
675 audio->samp_rate = audio->cfg.sample_rate;
676 audio->channel_mode = audio->cfg.channels;
677 audio->enc_type = ENC_TYPE_SBC;
678 break;
679 }
680 case AUDIO_SET_CONFIG: {
681 struct msm_audio_config cfg;
682 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
683 rc = -EFAULT;
684 break;
685 }
686 if (cfg.channel_count == 1) {
687 cfg.channel_count = AUDREC_CMD_MODE_MONO;
688 audio->buffer_size = MONO_DATA_SIZE;
689 } else if (cfg.channel_count == 2) {
690 cfg.channel_count = AUDREC_CMD_MODE_STEREO;
691 audio->buffer_size = STEREO_DATA_SIZE;
692 } else {
693 rc = -EINVAL;
694 break;
695 }
696 audio->samp_rate = cfg.sample_rate;
697 audio->channel_mode = cfg.channel_count;
698 audio->enc_type = ENC_TYPE_WAV;
699 break;
700 }
701 case AUDIO_GET_SBC_ENC_CONFIG: {
702 struct msm_audio_sbc_enc_config cfg;
703 memset(&cfg, 0, sizeof(cfg));
704 cfg.bit_allocation = audio->cfg.bit_allocation;
705 cfg.mode = audio->cfg.mode;
706 cfg.number_of_subbands = audio->cfg.number_of_subbands;
707 cfg.number_of_blocks = audio->cfg.number_of_blocks;
708 cfg.sample_rate = audio->samp_rate;
709 cfg.channels = audio->channel_mode;
710 cfg.bit_rate = audio->cfg.bit_rate;
711 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
712 rc = -EFAULT;
713 break;
714 }
715 case AUDIO_GET_CONFIG: {
716 struct msm_audio_config cfg;
717 memset(&cfg, 0, sizeof(cfg));
718 cfg.buffer_count = FRAME_NUM;
719 cfg.sample_rate = audio->samp_rate;
720 if (audio->channel_mode == AUDREC_CMD_MODE_MONO) {
721 cfg.channel_count = 1;
722 cfg.buffer_size = MONO_DATA_SIZE;
723 } else {
724 cfg.channel_count = 2;
725 cfg.buffer_size = STEREO_DATA_SIZE;
726 }
727 cfg.type = ENC_TYPE_WAV;
728 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
729 rc = -EFAULT;
730 break;
731 }
732 case AUDIO_GET_SESSION_ID: {
733 if (copy_to_user((void *) arg, &audio->enc_id,
734 sizeof(unsigned short))) {
735 rc = -EFAULT;
736 }
737 break;
738 }
739 default:
740 rc = -EINVAL;
741 }
742 mutex_unlock(&audio->lock);
743 return rc;
744}
745
746static ssize_t auda2dp_in_read(struct file *file,
747 char __user *buf,
748 size_t count, loff_t *pos)
749{
750 struct audio_a2dp_in *audio = file->private_data;
751 unsigned long flags;
752 const char __user *start = buf;
753 void *data;
754 uint32_t index;
755 uint32_t size;
756 int rc = 0;
757 uint32_t f_len = 0, f_num = 0;
758 int i = 0;
759
760 mutex_lock(&audio->read_lock);
761 while (count > 0) {
762 rc = wait_event_interruptible(
763 audio->wait, (audio->in_count > 0) || audio->stopped ||
764 audio->abort);
765
766 if (rc < 0)
767 break;
768
769 if (audio->stopped && !audio->in_count) {
770 MM_DBG("Driver in stop state, No more buffer to read");
771 rc = 0;/* End of File */
772 break;
773 }
774
775 if (audio->abort) {
776 rc = -EPERM; /* Not permitted due to abort */
777 break;
778 }
779
780 index = audio->in_tail;
781 data = (uint8_t *) audio->in[index].data;
782 size = audio->in[index].size;
783 if (count >= size) {
784 if (audio->enc_type == ENC_TYPE_SBC &&
785 (audio->in[index].frame_len % 2)) {
786 f_len = audio->in[index].frame_len;
787 f_num = audio->in[index].frame_num;
788 for (i = 0; i < f_num; i++) {
789 if (copy_to_user(&buf[i * f_len],
790 (uint8_t *) (data + (i * (f_len + 1))),
791 f_len)) {
792 rc = -EFAULT;
793 break;
794 }
795 }
796 } else {
797 if (copy_to_user(buf, data, size)) {
798 rc = -EFAULT;
799 break;
800 }
801 }
802 spin_lock_irqsave(&audio->dsp_lock, flags);
803 if (index != audio->in_tail) {
804 /* overrun -- data is
805 * invalid and we need to retry */
806 spin_unlock_irqrestore(&audio->dsp_lock, flags);
807 continue;
808 }
809 audio->in[index].size = 0;
810 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
811 audio->in_count--;
812 spin_unlock_irqrestore(&audio->dsp_lock, flags);
813 count -= size;
814 buf += size;
815 } else {
816 MM_ERR("short read\n");
817 break;
818 }
819 }
820 mutex_unlock(&audio->read_lock);
821 if (buf > start)
822 return buf - start;
823
824 return rc;
825}
826
827static ssize_t auda2dp_in_write(struct file *file,
828 const char __user *buf,
829 size_t count, loff_t *pos)
830{
831 return -EINVAL;
832}
833
834static int auda2dp_in_release(struct inode *inode, struct file *file)
835{
836 struct audio_a2dp_in *audio = file->private_data;
837
838 mutex_lock(&audio->lock);
839 /* with draw frequency for session
840 incase not stopped the driver */
841 msm_snddev_withdraw_freq(audio->enc_id, SNDDEV_CAP_TX,
842 AUDDEV_CLNT_ENC);
843 auddev_unregister_evt_listner(AUDDEV_CLNT_ENC, audio->enc_id);
844 /*reset the sampling frequency information at audpreproc layer*/
845 audio->session_info.sampling_freq = 0;
846 audpreproc_update_audrec_info(&audio->session_info);
847 auda2dp_in_disable(audio);
848 auda2dp_in_flush(audio);
849 msm_adsp_put(audio->audrec);
850 audpreproc_aenc_free(audio->enc_id);
851 audio->audrec = NULL;
852 audio->opened = 0;
853 if (audio->data) {
Sidipotu Ashok823c1532012-10-04 15:20:24 +0530854 ion_unmap_kernel(audio->client, audio->output_buff_handle);
855 ion_free(audio->client, audio->output_buff_handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700856 audio->data = NULL;
857 }
Sidipotu Ashok823c1532012-10-04 15:20:24 +0530858 ion_client_destroy(audio->client);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700859 mutex_unlock(&audio->lock);
860 return 0;
861}
862
863static int auda2dp_in_open(struct inode *inode, struct file *file)
864{
865 struct audio_a2dp_in *audio = &the_audio_a2dp_in;
866 int rc;
867 int encid;
Sidipotu Ashok823c1532012-10-04 15:20:24 +0530868 int len = 0;
869 unsigned long ionflag = 0;
870 ion_phys_addr_t addr = 0;
871 struct ion_handle *handle = NULL;
872 struct ion_client *client = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700873
874 mutex_lock(&audio->lock);
875 if (audio->opened) {
876 rc = -EBUSY;
877 goto done;
878 }
879
Sidipotu Ashok823c1532012-10-04 15:20:24 +0530880 client = msm_ion_client_create(UINT_MAX, "Audio_a2dp_in_client");
881 if (IS_ERR_OR_NULL(client)) {
882 MM_ERR("Unable to create ION client\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700883 rc = -ENOMEM;
Sidipotu Ashok823c1532012-10-04 15:20:24 +0530884 goto client_create_error;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700885 }
Sidipotu Ashok823c1532012-10-04 15:20:24 +0530886 audio->client = client;
887
888 MM_DBG("allocating mem sz = %d\n", DMASZ);
889 handle = ion_alloc(client, DMASZ, SZ_4K,
890 ION_HEAP(ION_AUDIO_HEAP_ID), 0);
891 if (IS_ERR_OR_NULL(handle)) {
892 MM_ERR("Unable to create allocate O/P buffers\n");
893 rc = -ENOMEM;
894 goto output_buff_alloc_error;
895 }
896
897 audio->output_buff_handle = handle;
898
899 rc = ion_phys(client , handle, &addr, &len);
900 if (rc) {
901 MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
902 (unsigned int) addr, (unsigned int) len);
903 rc = -ENOMEM;
904 goto output_buff_get_phys_error;
905 } else {
906 MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
907 (unsigned int) addr, (unsigned int) len);
908 }
909 audio->phys = (int32_t)addr;
910
911 rc = ion_handle_get_flags(client, handle, &ionflag);
912 if (rc) {
913 MM_ERR("could not get flags for the handle\n");
914 rc = -ENOMEM;
915 goto output_buff_get_flags_error;
916 }
917
918 audio->msm_map = ion_map_kernel(client, handle);
919 if (IS_ERR(audio->data)) {
920 MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
921 (int)audio);
922 rc = -ENOMEM;
923 goto output_buff_map_error;
924 }
925 MM_DBG("read buf: phy addr 0x%08x kernel addr 0x%08x\n",
926 audio->phys, (int)audio->data);
927
928 audio->data = (char *)audio->msm_map;
929
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700930 MM_DBG("Memory addr = 0x%8x phy addr = 0x%8x\n",\
931 (int) audio->data, (int) audio->phys);
932
933 if ((file->f_mode & FMODE_WRITE) &&
934 (file->f_mode & FMODE_READ)) {
935 rc = -EACCES;
936 MM_ERR("Non tunnel encoding is not supported\n");
937 goto done;
938 } else if (!(file->f_mode & FMODE_WRITE) &&
939 (file->f_mode & FMODE_READ)) {
940 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
941 MM_DBG("Opened for Tunnel mode encoding\n");
942 } else {
943 rc = -EACCES;
944 goto done;
945 }
946 /* Settings will be re-config at AUDIO_SET_CONFIG/SBC_ENC_CONFIG,
947 * but at least we need to have initial config
948 */
949 audio->channel_mode = AUDREC_CMD_MODE_MONO;
950 audio->buffer_size = FRAME_SIZE_SBC;
951 audio->samp_rate = 48000;
952 audio->enc_type = ENC_TYPE_SBC | audio->mode;
953 audio->cfg.bit_allocation = AUDIO_SBC_BA_SNR;
954 audio->cfg.mode = AUDIO_SBC_MODE_JSTEREO;
955 audio->cfg.number_of_subbands = AUDIO_SBC_BANDS_8;
956 audio->cfg.number_of_blocks = AUDIO_SBC_BLOCKS_16;
957 audio->cfg.bit_rate = 320000; /* max 512kbps(mono), 320kbs(others) */
958
959 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
960 &audio->queue_ids);
961 if (encid < 0) {
962 MM_ERR("No free encoder available\n");
963 rc = -ENODEV;
964 goto done;
965 }
966 audio->enc_id = encid;
967
968 rc = msm_adsp_get(audio->module_name, &audio->audrec,
969 &audrec_adsp_ops, audio);
970
971 if (rc) {
972 audpreproc_aenc_free(audio->enc_id);
973 goto done;
974 }
975
976 audio->stopped = 0;
977 audio->source = 0;
978 audio->abort = 0;
979 auda2dp_in_flush(audio);
980 audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS |
981 AUDDEV_EVT_FREQ_CHG;
982
983 rc = auddev_register_evt_listner(audio->device_events,
984 AUDDEV_CLNT_ENC, audio->enc_id,
985 a2dp_in_listener, (void *) audio);
986 if (rc) {
987 MM_ERR("failed to register device event listener\n");
988 goto evt_error;
989 }
Kalyani polepeddy7413d2b2011-10-14 15:42:15 +0530990 audio->build_id = socinfo_get_build_id();
Vinay Vaka4ff52a62011-12-13 15:38:35 +0530991 MM_DBG("Modem build id = %s\n", audio->build_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700992 file->private_data = audio;
993 audio->opened = 1;
994 rc = 0;
995done:
996 mutex_unlock(&audio->lock);
997 return rc;
998evt_error:
Sidipotu Ashok823c1532012-10-04 15:20:24 +0530999output_buff_map_error:
1000output_buff_get_phys_error:
1001output_buff_get_flags_error:
1002 ion_free(client, audio->output_buff_handle);
1003output_buff_alloc_error:
1004 ion_client_destroy(client);
1005client_create_error:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001006 msm_adsp_put(audio->audrec);
1007 audpreproc_aenc_free(audio->enc_id);
1008 mutex_unlock(&audio->lock);
1009 return rc;
1010}
1011
1012static const struct file_operations audio_a2dp_in_fops = {
1013 .owner = THIS_MODULE,
1014 .open = auda2dp_in_open,
1015 .release = auda2dp_in_release,
1016 .read = auda2dp_in_read,
1017 .write = auda2dp_in_write,
1018 .unlocked_ioctl = auda2dp_in_ioctl,
1019};
1020
1021struct miscdevice audio_a2dp_in_misc = {
1022 .minor = MISC_DYNAMIC_MINOR,
1023 .name = "msm_a2dp_in",
1024 .fops = &audio_a2dp_in_fops,
1025};
1026
1027static int __init auda2dp_in_init(void)
1028{
1029 mutex_init(&the_audio_a2dp_in.lock);
1030 mutex_init(&the_audio_a2dp_in.read_lock);
1031 spin_lock_init(&the_audio_a2dp_in.dsp_lock);
1032 spin_lock_init(&the_audio_a2dp_in.dev_lock);
1033 init_waitqueue_head(&the_audio_a2dp_in.wait);
1034 init_waitqueue_head(&the_audio_a2dp_in.wait_enable);
1035 return misc_register(&audio_a2dp_in_misc);
1036}
1037
1038device_initcall(auda2dp_in_init);
1039
1040MODULE_DESCRIPTION("MSM SBC encode driver");
1041MODULE_LICENSE("GPL v2");