blob: 7f0d68afc84976eaea5af48941817d2d2a496f13 [file] [log] [blame]
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301
2/* audio_lpa.c - low power audio driver
3 *
Duy Truong790f06d2013-02-13 16:38:12 -08004 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Sidipotu Ashok0a690212012-02-21 17:18:53 +05305 *
6 * Based on the PCM decoder driver in arch/arm/mach-msm/qdsp5/audio_pcm.c
7 *
8 * Copyright (C) 2008 Google, Inc.
9 * Copyright (C) 2008 HTC Corporation
10 *
11 * All source code in this file is licensed under the following license except
12 * where indicated.
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License version 2 as published
16 * by the Free Software Foundation.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 *
22 * See the GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, you can find it at http://www.fsf.org
25 */
26
27#include <asm/atomic.h>
28#include <asm/ioctls.h>
29
30#include <linux/module.h>
31#include <linux/fs.h>
32#include <linux/miscdevice.h>
33#include <linux/uaccess.h>
34#include <linux/kthread.h>
35#include <linux/wait.h>
36#include <linux/dma-mapping.h>
37#include <linux/debugfs.h>
38#include <linux/delay.h>
39#include <linux/earlysuspend.h>
Mitchel Humpherys1da6ebe2012-09-06 10:15:56 -070040#include <linux/msm_ion.h>
Sidipotu Ashok0a690212012-02-21 17:18:53 +053041#include <linux/list.h>
Sidipotu Ashok0a690212012-02-21 17:18:53 +053042#include <linux/slab.h>
43#include <linux/msm_audio.h>
44
45
46#include <mach/msm_adsp.h>
47#include <mach/iommu.h>
48#include <mach/iommu_domains.h>
Sidipotu Ashok0a690212012-02-21 17:18:53 +053049#include <mach/qdsp5/qdsp5audppcmdi.h>
50#include <mach/qdsp5/qdsp5audppmsg.h>
Manish Dewanganfa8a6b62012-07-09 16:23:27 +053051#include <mach/qdsp5/qdsp5audpp.h>
Sidipotu Ashok0a690212012-02-21 17:18:53 +053052#include <mach/qdsp5/qdsp5audplaycmdi.h>
53#include <mach/qdsp5/qdsp5audplaymsg.h>
54#include <mach/qdsp5/qdsp5rmtcmdi.h>
55#include <mach/debug_mm.h>
56#include <linux/memory_alloc.h>
57#include <mach/msm_memtypes.h>
58
59#include "audmgr.h"
60
61/* for queue ids - should be relative to module number*/
62#include "adsp.h"
63
64#define ADRV_STATUS_AIO_INTF 0x00000001
65#define ADRV_STATUS_OBUF_GIVEN 0x00000002
66#define ADRV_STATUS_IBUF_GIVEN 0x00000004
67#define ADRV_STATUS_FSYNC 0x00000008
68
69#define MSM_MAX_VOLUME 0x2000
70/* 17 added to avoid more deviation */
71#define MSM_VOLUME_STEP (MSM_MAX_VOLUME+17)
72#define MSM_VOLUME_FACTOR (10000)
73
74/* Size must be power of 2 */
75#define MAX_BUF 2
Sidipotu Ashokfeff0ff2012-05-04 09:18:39 +053076#define BUFSZ (524288)
Sidipotu Ashok0a690212012-02-21 17:18:53 +053077
78#define AUDDEC_DEC_PCM 0
79
80/* Decoder status received from AUDPPTASK */
81#define AUDPP_DEC_STATUS_SLEEP 0
82#define AUDPP_DEC_STATUS_INIT 1
83#define AUDPP_DEC_STATUS_CFG 2
84#define AUDPP_DEC_STATUS_PLAY 3
85
86#define AUDPCM_EVENT_NUM 10 /* Default number of pre-allocated event packets */
87
88#define __CONTAINS(r, v, l) ({ \
89 typeof(r) __r = r; \
90 typeof(v) __v = v; \
91 typeof(v) __e = __v + l; \
92 int res = ((__v >= __r->vaddr) && \
93 (__e <= __r->vaddr + __r->len)); \
94 res; \
95})
96
97#define CONTAINS(r1, r2) ({ \
98 typeof(r2) __r2 = r2; \
99 __CONTAINS(r1, __r2->vaddr, __r2->len); \
100})
101
102#define IN_RANGE(r, v) ({ \
103 typeof(r) __r = r; \
104 typeof(v) __vv = v; \
105 int res = ((__vv >= __r->vaddr) && \
106 (__vv < (__r->vaddr + __r->len))); \
107 res; \
108})
109
110#define OVERLAPS(r1, r2) ({ \
111 typeof(r1) __r1 = r1; \
112 typeof(r2) __r2 = r2; \
113 typeof(__r2->vaddr) __v = __r2->vaddr; \
114 typeof(__v) __e = __v + __r2->len - 1; \
115 int res = (IN_RANGE(__r1, __v) || IN_RANGE(__r1, __e)); \
116 res; \
117})
118
119struct audio;
120
121struct buffer {
122 void *data;
123 unsigned size;
124 unsigned used; /* Input usage actual DSP produced PCM size */
125 unsigned addr;
126};
127
128#ifdef CONFIG_HAS_EARLYSUSPEND
129struct audpcm_suspend_ctl {
130struct early_suspend node;
131struct audio *audio;
132};
133#endif
134
135struct audpcm_event {
136 struct list_head list;
137 int event_type;
138 union msm_audio_event_payload payload;
139};
140
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530141struct audlpa_ion_region {
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530142 struct list_head list;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530143 struct ion_handle *handle;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530144 int fd;
145 void *vaddr;
146 unsigned long paddr;
147 unsigned long kvaddr;
148 unsigned long len;
149 unsigned ref_cnt;
150};
151
152struct audpcm_buffer_node {
153 struct list_head list;
154 struct msm_audio_aio_buf buf;
155 unsigned long paddr;
156};
157
158struct audio {
159 struct buffer out[2];
160
161 spinlock_t dsp_lock;
162
163 uint8_t out_head;
164 uint8_t out_tail;
165 uint8_t out_needed; /* number of buffers the dsp is waiting for */
166 struct list_head out_queue; /* queue to retain output buffers */
167 atomic_t out_bytes;
168
169 struct mutex lock;
170 struct mutex write_lock;
171 wait_queue_head_t write_wait;
172
173 struct msm_adsp_module *audplay;
174
175 /* configuration to use on next enable */
176 uint32_t out_sample_rate;
177 uint32_t out_channel_mode;
178 uint32_t out_bits; /* bits per sample */
179
180 struct audmgr audmgr;
181
182 /* data allocated for various buffers */
183 char *data;
184 int32_t phys;
185 struct msm_mapped_buffer *map_v_write;
186
187 uint32_t drv_status;
188 int wflush; /* Write flush */
189 int opened;
190 int enabled;
191 int running;
192 int stopped; /* set when stopped, cleared on flush */
193 int teos; /* valid only if tunnel mode & no data left for decoder */
194 int rmt_resource_released;
195 enum msm_aud_decoder_state dec_state; /* Represents decoder state */
196 int reserved; /* A byte is being reserved */
197 char rsv_byte; /* Handle odd length user data */
198
199 const char *module_name;
200 unsigned queue_id;
201
202 unsigned long volume;
203
204 uint16_t dec_id;
205
206#ifdef CONFIG_HAS_EARLYSUSPEND
207 struct audpcm_suspend_ctl suspend_ctl;
208#endif
209
210#ifdef CONFIG_DEBUG_FS
211 struct dentry *dentry;
212#endif
213 wait_queue_head_t wait;
214 struct list_head free_event_queue;
215 struct list_head event_queue;
216 wait_queue_head_t event_wait;
217 spinlock_t event_queue_lock;
218 struct mutex get_event_lock;
219 int event_abort;
220
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530221 struct list_head ion_region_queue;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530222 int buffer_count;
223 int buffer_size;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530224 struct ion_client *client;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530225};
226
227static int auddec_dsp_config(struct audio *audio, int enable);
228static void audpp_cmd_cfg_adec_params(struct audio *audio);
229static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
230static void audpcm_post_event(struct audio *audio, int type,
231 union msm_audio_event_payload payload);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530232static unsigned long audlpa_ion_fixup(struct audio *audio, void *addr,
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530233 unsigned long len, int ref_up);
234static void audpcm_async_send_data(struct audio *audio,
235 unsigned needed);
236
237
238static int rmt_put_resource(struct audio *audio)
239{
240 struct aud_codec_config_cmd cmd;
241 unsigned short client_idx;
242
243 cmd.cmd_id = RM_CMD_AUD_CODEC_CFG;
244 cmd.client_id = RM_AUD_CLIENT_ID;
245 cmd.task_id = audio->dec_id;
246 cmd.enable = RMT_DISABLE;
247 cmd.dec_type = AUDDEC_DEC_PCM;
248 client_idx = ((cmd.client_id << 8) | cmd.task_id);
249
250 return put_adsp_resource(client_idx, &cmd, sizeof(cmd));
251}
252
253static int rmt_get_resource(struct audio *audio)
254{
255 struct aud_codec_config_cmd cmd;
256 unsigned short client_idx;
257
258 cmd.cmd_id = RM_CMD_AUD_CODEC_CFG;
259 cmd.client_id = RM_AUD_CLIENT_ID;
260 cmd.task_id = audio->dec_id;
261 cmd.enable = RMT_ENABLE;
262 cmd.dec_type = AUDDEC_DEC_PCM;
263 client_idx = ((cmd.client_id << 8) | cmd.task_id);
264
265 return get_adsp_resource(client_idx, &cmd, sizeof(cmd));
266}
267
268/* must be called with audio->lock held */
269static int audio_enable(struct audio *audio)
270{
271 struct audmgr_config cfg;
272 int rc;
273
274 MM_DBG("\n"); /* Macro prints the file name and function */
275 if (audio->enabled)
276 return 0;
277
278 if (audio->rmt_resource_released == 1) {
279 audio->rmt_resource_released = 0;
280 rc = rmt_get_resource(audio);
281 if (rc)
282 MM_ERR("ADSP resources are not available");
283 }
284
285 audio->dec_state = MSM_AUD_DECODER_STATE_NONE;
286 audio->out_tail = 0;
287 audio->out_needed = 0;
288
289 cfg.tx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
290 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_48000;
291 cfg.def_method = RPC_AUD_DEF_METHOD_PLAYBACK;
292 cfg.codec = RPC_AUD_DEF_CODEC_PCM;
293 cfg.snd_method = RPC_SND_METHOD_MIDI;
294
295 rc = audmgr_enable(&audio->audmgr, &cfg);
=Chaithanya Krishna Bacharajub5c4e982012-12-06 09:53:18 +0530296 if (rc < 0) {
297 msm_adsp_dump(audio->audplay);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530298 return rc;
=Chaithanya Krishna Bacharajub5c4e982012-12-06 09:53:18 +0530299 }
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530300 if (msm_adsp_enable(audio->audplay)) {
301 MM_ERR("msm_adsp_enable(audplay) failed\n");
302 audmgr_disable(&audio->audmgr);
303 return -ENODEV;
304 }
305
306 if (audpp_enable(audio->dec_id, audio_dsp_event, audio)) {
307 MM_ERR("audpp_enable() failed\n");
308 msm_adsp_disable(audio->audplay);
309 audmgr_disable(&audio->audmgr);
310 return -ENODEV;
311 }
312
313 audio->enabled = 1;
314 return 0;
315}
316
317/* must be called with audio->lock held */
318static int audio_disable(struct audio *audio)
319{
320 int rc = 0;
321 MM_DBG("\n"); /* Macro prints the file name and function */
322 if (audio->enabled) {
323 audio->enabled = 0;
324 audio->dec_state = MSM_AUD_DECODER_STATE_NONE;
325 auddec_dsp_config(audio, 0);
326 rc = wait_event_interruptible_timeout(audio->wait,
327 audio->dec_state != MSM_AUD_DECODER_STATE_NONE,
328 msecs_to_jiffies(MSM_AUD_DECODER_WAIT_MS));
329 if (rc == 0)
330 rc = -ETIMEDOUT;
331 else if (audio->dec_state != MSM_AUD_DECODER_STATE_CLOSE)
332 rc = -EFAULT;
333 else
334 rc = 0;
335 audio->stopped = 1;
336 wake_up(&audio->write_wait);
337 msm_adsp_disable(audio->audplay);
338 audpp_disable(audio->dec_id, audio);
=Chaithanya Krishna Bacharajub5c4e982012-12-06 09:53:18 +0530339 rc = audmgr_disable(&audio->audmgr);
340 if (rc < 0)
341 msm_adsp_dump(audio->audplay);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530342 audio->out_needed = 0;
343 rmt_put_resource(audio);
344 audio->rmt_resource_released = 1;
345 }
346 return rc;
347}
348
349/* ------------------- dsp --------------------- */
350static void audplay_dsp_event(void *data, unsigned id, size_t len,
351 void (*getevent) (void *ptr, size_t len))
352{
353 struct audio *audio = data;
354 uint32_t msg[28];
355 getevent(msg, sizeof(msg));
356
357 MM_DBG("msg_id=%x\n", id);
358
359 switch (id) {
360 case AUDPLAY_MSG_DEC_NEEDS_DATA:
361 audpcm_async_send_data(audio, 1);
362 break;
363 case ADSP_MESSAGE_ID:
364 MM_DBG("Received ADSP event: module enable(audplaytask)\n");
365 break;
366 default:
367 MM_ERR("unexpected message from decoder\n");
368 break;
369 }
370}
371
372static void audio_dsp_event(void *private, unsigned id, uint16_t *msg)
373{
374 struct audio *audio = private;
375
376 switch (id) {
377 case AUDPP_MSG_STATUS_MSG:{
378 unsigned status = msg[1];
379
380 switch (status) {
381 case AUDPP_DEC_STATUS_SLEEP: {
382 uint16_t reason = msg[2];
383 MM_DBG("decoder status: sleep reason =0x%04x\n",
384 reason);
385 if ((reason == AUDPP_MSG_REASON_MEM)
386 || (reason ==
387 AUDPP_MSG_REASON_NODECODER)) {
388 audio->dec_state =
389 MSM_AUD_DECODER_STATE_FAILURE;
390 wake_up(&audio->wait);
391 } else if (reason == AUDPP_MSG_REASON_NONE) {
392 /* decoder is in disable state */
393 audio->dec_state =
394 MSM_AUD_DECODER_STATE_CLOSE;
395 wake_up(&audio->wait);
396 }
397 break;
398 }
399 case AUDPP_DEC_STATUS_INIT:
400 MM_DBG("decoder status: init\n");
401 audpp_cmd_cfg_adec_params(audio);
402 break;
403
404 case AUDPP_DEC_STATUS_CFG:
405 MM_DBG("decoder status: cfg\n");
406 break;
407 case AUDPP_DEC_STATUS_PLAY:
408 MM_DBG("decoder status: play\n");
409 audio->dec_state =
410 MSM_AUD_DECODER_STATE_SUCCESS;
411 wake_up(&audio->wait);
412 break;
413 default:
414 MM_ERR("unknown decoder status\n");
415 break;
416 }
417 break;
418 }
419 case AUDPP_MSG_CFG_MSG:
420 if (msg[0] == AUDPP_MSG_ENA_ENA) {
421 MM_DBG("CFG_MSG ENABLE\n");
422 auddec_dsp_config(audio, 1);
423 audio->out_needed = 0;
424 audio->running = 1;
425 audpp_set_volume_and_pan(audio->dec_id, audio->volume,
426 0);
427 } else if (msg[0] == AUDPP_MSG_ENA_DIS) {
428 MM_DBG("CFG_MSG DISABLE\n");
429 audio->running = 0;
430 } else {
431 MM_ERR("CFG_MSG %d?\n", msg[0]);
432 }
433 break;
434 case AUDPP_MSG_FLUSH_ACK:
435 MM_DBG("FLUSH_ACK\n");
436 audio->wflush = 0;
437 wake_up(&audio->write_wait);
438 break;
439
440 case AUDPP_MSG_PCMDMAMISSED:
441 MM_DBG("PCMDMAMISSED\n");
442 audio->teos = 1;
443 wake_up(&audio->write_wait);
444 break;
445
446 default:
447 MM_ERR("UNKNOWN (%d)\n", id);
448 }
449
450}
451
452
453struct msm_adsp_ops audlpadec_adsp_ops = {
454 .event = audplay_dsp_event,
455};
456
457
458#define audplay_send_queue0(audio, cmd, len) \
459 msm_adsp_write(audio->audplay, audio->queue_id, \
460 cmd, len)
461
462static int auddec_dsp_config(struct audio *audio, int enable)
463{
464 u16 cfg_dec_cmd[AUDPP_CMD_CFG_DEC_TYPE_LEN / sizeof(unsigned short)];
465
466 memset(cfg_dec_cmd, 0, sizeof(cfg_dec_cmd));
467
468 cfg_dec_cmd[0] = AUDPP_CMD_CFG_DEC_TYPE;
469 if (enable)
470 cfg_dec_cmd[1 + audio->dec_id] = AUDPP_CMD_UPDATDE_CFG_DEC |
Phani Kumar Alladaae39d6d2012-06-12 11:52:20 +0530471 AUDPP_CMD_ENA_DEC_V | AUDDEC_DEC_PCM |
472 AUDPP_CMD_LPA_MODE;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530473 else
474 cfg_dec_cmd[1 + audio->dec_id] = AUDPP_CMD_UPDATDE_CFG_DEC |
475 AUDPP_CMD_DIS_DEC_V;
476
477 return audpp_send_queue1(&cfg_dec_cmd, sizeof(cfg_dec_cmd));
478}
479
480static void audpp_cmd_cfg_adec_params(struct audio *audio)
481{
482 audpp_cmd_cfg_adec_params_wav cmd;
483
484 memset(&cmd, 0, sizeof(cmd));
485 cmd.common.cmd_id = AUDPP_CMD_CFG_ADEC_PARAMS;
486 cmd.common.length = AUDPP_CMD_CFG_ADEC_PARAMS_WAV_LEN;
487 cmd.common.dec_id = audio->dec_id;
488 cmd.common.input_sampling_frequency = audio->out_sample_rate;
489 cmd.stereo_cfg = audio->out_channel_mode;
490 cmd.pcm_width = audio->out_bits;
491 cmd.sign = 0;
492 audpp_send_queue2(&cmd, sizeof(cmd));
493}
494static void audpcm_async_send_data(struct audio *audio, unsigned needed)
495{
496 unsigned long flags;
497
498 if (!audio->running)
499 return;
500
501 spin_lock_irqsave(&audio->dsp_lock, flags);
502
503 if (needed && !audio->wflush) {
504 audio->out_needed = 1;
505 if (audio->drv_status & ADRV_STATUS_OBUF_GIVEN) {
506 /* pop one node out of queue */
507 union msm_audio_event_payload payload;
508 struct audpcm_buffer_node *used_buf;
509
510 MM_DBG("consumed\n");
511
512 BUG_ON(list_empty(&audio->out_queue));
513 used_buf = list_first_entry(&audio->out_queue,
514 struct audpcm_buffer_node, list);
515 list_del(&used_buf->list);
516 payload.aio_buf = used_buf->buf;
517 audpcm_post_event(audio, AUDIO_EVENT_WRITE_DONE,
518 payload);
519 kfree(used_buf);
520 audio->drv_status &= ~ADRV_STATUS_OBUF_GIVEN;
521 }
522 }
523 if (audio->out_needed) {
524 struct audpcm_buffer_node *next_buf;
525 audplay_cmd_bitstream_data_avail cmd;
526 if (!list_empty(&audio->out_queue)) {
527 next_buf = list_first_entry(&audio->out_queue,
528 struct audpcm_buffer_node, list);
529 MM_DBG("next_buf %p\n", next_buf);
530 if (next_buf) {
531 MM_DBG("next buf phy %lx len %d\n",
532 next_buf->paddr, next_buf->buf.data_len);
533
534 cmd.cmd_id = AUDPLAY_CMD_BITSTREAM_DATA_AVAIL;
535 if (next_buf->buf.data_len)
536 cmd.decoder_id = audio->dec_id;
537 else {
538 cmd.decoder_id = -1;
539 MM_DBG("input EOS signaled\n");
540 }
541 cmd.buf_ptr = (unsigned) next_buf->paddr;
542 cmd.buf_size = next_buf->buf.data_len >> 1;
543 cmd.partition_number = 0;
544 /* complete writes to the input buffer */
545 wmb();
546 audplay_send_queue0(audio, &cmd, sizeof(cmd));
547 audio->out_needed = 0;
548 audio->drv_status |= ADRV_STATUS_OBUF_GIVEN;
549 }
550 }
551 }
552 spin_unlock_irqrestore(&audio->dsp_lock, flags);
553}
554
555/* ------------------- device --------------------- */
556static void audpcm_async_flush(struct audio *audio)
557{
558 struct audpcm_buffer_node *buf_node;
559 struct list_head *ptr, *next;
560 union msm_audio_event_payload payload;
Chaithanya Krishna Bacharaju221f7992012-05-16 09:32:54 +0530561 unsigned long flags;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530562
Chaithanya Krishna Bacharaju221f7992012-05-16 09:32:54 +0530563 spin_lock_irqsave(&audio->dsp_lock, flags);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530564 MM_DBG("\n"); /* Macro prints the file name and function */
565 list_for_each_safe(ptr, next, &audio->out_queue) {
566 buf_node = list_entry(ptr, struct audpcm_buffer_node, list);
567 list_del(&buf_node->list);
568 payload.aio_buf = buf_node->buf;
569 audpcm_post_event(audio, AUDIO_EVENT_WRITE_DONE,
570 payload);
571 kfree(buf_node);
572 }
573 audio->drv_status &= ~ADRV_STATUS_OBUF_GIVEN;
574 audio->out_needed = 0;
575 atomic_set(&audio->out_bytes, 0);
Chaithanya Krishna Bacharaju221f7992012-05-16 09:32:54 +0530576 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530577}
578static void audio_ioport_reset(struct audio *audio)
579{
580 if (audio->drv_status & ADRV_STATUS_AIO_INTF) {
581 /* If fsync is in progress, make sure
582 * return value of fsync indicates
583 * abort due to flush
584 */
585 if (audio->drv_status & ADRV_STATUS_FSYNC) {
586 MM_DBG("fsync in progress\n");
587 wake_up(&audio->write_wait);
588 mutex_lock(&audio->write_lock);
589 audpcm_async_flush(audio);
590 mutex_unlock(&audio->write_lock);
591 } else
592 audpcm_async_flush(audio);
593 } else {
594 /* Make sure read/write thread are free from
595 * sleep and knowing that system is not able
596 * to process io request at the moment
597 */
598 wake_up(&audio->write_wait);
599 mutex_lock(&audio->write_lock);
600 audpcm_async_flush(audio);
601 mutex_unlock(&audio->write_lock);
602 }
603}
604
605static int audpcm_events_pending(struct audio *audio)
606{
607 unsigned long flags;
608 int empty;
609
610 spin_lock_irqsave(&audio->event_queue_lock, flags);
611 empty = !list_empty(&audio->event_queue);
612 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
613 return empty || audio->event_abort;
614}
615
616static void audpcm_reset_event_queue(struct audio *audio)
617{
618 unsigned long flags;
619 struct audpcm_event *drv_evt;
620 struct list_head *ptr, *next;
621
622 spin_lock_irqsave(&audio->event_queue_lock, flags);
623 list_for_each_safe(ptr, next, &audio->event_queue) {
624 drv_evt = list_first_entry(&audio->event_queue,
625 struct audpcm_event, list);
626 list_del(&drv_evt->list);
627 kfree(drv_evt);
628 }
629 list_for_each_safe(ptr, next, &audio->free_event_queue) {
630 drv_evt = list_first_entry(&audio->free_event_queue,
631 struct audpcm_event, list);
632 list_del(&drv_evt->list);
633 kfree(drv_evt);
634 }
635 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
636
637 return;
638}
639
640static long audpcm_process_event_req(struct audio *audio, void __user *arg)
641{
642 long rc;
643 struct msm_audio_event usr_evt;
644 struct audpcm_event *drv_evt = NULL;
645 int timeout;
646 unsigned long flags;
647
648 if (copy_from_user(&usr_evt, arg, sizeof(struct msm_audio_event)))
649 return -EFAULT;
650
651 timeout = (int) usr_evt.timeout_ms;
652
653 if (timeout > 0) {
654 rc = wait_event_interruptible_timeout(
655 audio->event_wait, audpcm_events_pending(audio),
656 msecs_to_jiffies(timeout));
657 if (rc == 0)
658 return -ETIMEDOUT;
659 } else {
660 rc = wait_event_interruptible(
661 audio->event_wait, audpcm_events_pending(audio));
662 }
663
664 if (rc < 0)
665 return rc;
666
667 if (audio->event_abort) {
668 audio->event_abort = 0;
669 return -ENODEV;
670 }
671
672 spin_lock_irqsave(&audio->event_queue_lock, flags);
673 if (!list_empty(&audio->event_queue)) {
674 drv_evt = list_first_entry(&audio->event_queue,
675 struct audpcm_event, list);
676 list_del(&drv_evt->list);
677 }
678 if (drv_evt) {
679 usr_evt.event_type = drv_evt->event_type;
680 usr_evt.event_payload = drv_evt->payload;
681 list_add_tail(&drv_evt->list, &audio->free_event_queue);
682 } else
683 rc = -1;
684 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
685
686 if (drv_evt && drv_evt->event_type == AUDIO_EVENT_WRITE_DONE) {
687 mutex_lock(&audio->lock);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530688 audlpa_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530689 drv_evt->payload.aio_buf.buf_len, 0);
690 mutex_unlock(&audio->lock);
691 }
692 if (!rc && copy_to_user(arg, &usr_evt, sizeof(usr_evt)))
693 rc = -EFAULT;
694
695 return rc;
696}
697
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530698static int audlpa_ion_check(struct audio *audio,
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530699 void *vaddr, unsigned long len)
700{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530701 struct audlpa_ion_region *region_elt;
702 struct audlpa_ion_region t = {.vaddr = vaddr, .len = len };
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530703
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530704 list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530705 if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
706 OVERLAPS(region_elt, &t)) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530707 MM_ERR("[%p]:region (vaddr %p len %ld)"
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530708 " clashes with registered region"
709 " (vaddr %p paddr %p len %ld)\n",
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530710 audio, vaddr, len,
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530711 region_elt->vaddr,
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530712 (void *)region_elt->paddr, region_elt->len);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530713 return -EINVAL;
714 }
715 }
716
717 return 0;
718}
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530719static int audlpa_ion_add(struct audio *audio,
720 struct msm_audio_ion_info *info)
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530721{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530722 ion_phys_addr_t paddr;
723 size_t len;
724 unsigned long kvaddr;
725 struct audlpa_ion_region *region;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530726 int rc = -EINVAL;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530727 struct ion_handle *handle;
728 unsigned long ionflag;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530729
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530730 MM_ERR("\n"); /* Macro prints the file name and function */
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530731 region = kmalloc(sizeof(*region), GFP_KERNEL);
732
733 if (!region) {
734 rc = -ENOMEM;
735 goto end;
736 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530737 handle = ion_import_dma_buf(audio->client, info->fd);
738 if (IS_ERR_OR_NULL(handle)) {
739 pr_err("%s: could not get handle of the given fd\n", __func__);
740 goto import_error;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530741 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530742 rc = ion_handle_get_flags(audio->client, handle, &ionflag);
743 if (rc) {
744 pr_err("%s: could not get flags for the handle\n", __func__);
745 goto flag_error;
746 }
Mitchel Humpherys911b4b72012-09-12 14:42:50 -0700747 kvaddr = (unsigned long)ion_map_kernel(audio->client, handle);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530748 if (IS_ERR_OR_NULL((void *)kvaddr)) {
749 pr_err("%s: could not get virtual address\n", __func__);
750 goto map_error;
751 }
752 rc = ion_phys(audio->client, handle, &paddr, &len);
753 if (rc) {
754 pr_err("%s: could not get physical address\n", __func__);
755 goto ion_error;
756 }
757 rc = audlpa_ion_check(audio, info->vaddr, len);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530758 if (rc < 0) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530759 MM_ERR("audpcm_ion_check failed\n");
760 goto ion_error;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530761 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530762 region->handle = handle;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530763 region->vaddr = info->vaddr;
764 region->fd = info->fd;
765 region->paddr = paddr;
766 region->kvaddr = kvaddr;
767 region->len = len;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530768 region->ref_cnt = 0;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530769 MM_DBG("[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
770 audio, region->paddr, region->vaddr,
771 region->len, region->kvaddr);
772 list_add_tail(&region->list, &audio->ion_region_queue);
773
774 return rc;
775
776ion_error:
777 ion_unmap_kernel(audio->client, handle);
778map_error:
779flag_error:
780 ion_free(audio->client, handle);
781import_error:
782 kfree(region);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530783end:
784 return rc;
785}
786
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530787static int audlpa_ion_remove(struct audio *audio,
788 struct msm_audio_ion_info *info)
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530789{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530790 struct audlpa_ion_region *region;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530791 struct list_head *ptr, *next;
792 int rc = -EINVAL;
793
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530794 list_for_each_safe(ptr, next, &audio->ion_region_queue) {
795 region = list_entry(ptr, struct audlpa_ion_region, list);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530796
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530797 if (region != NULL && (region->fd == info->fd) &&
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530798 (region->vaddr == info->vaddr)) {
799 if (region->ref_cnt) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530800 MM_DBG("%s[%p]:region %p in use ref_cnt %d\n",
801 __func__, audio, region,
802 region->ref_cnt);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530803 break;
804 }
805 MM_DBG("remove region fd %d vaddr %p\n",
806 info->fd, info->vaddr);
807 list_del(&region->list);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530808 ion_unmap_kernel(audio->client, region->handle);
809 ion_free(audio->client, region->handle);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530810 kfree(region);
811 rc = 0;
812 break;
813 }
814 }
815
816 return rc;
817}
818
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530819static int audlpa_ion_lookup_vaddr(struct audio *audio, void *addr,
820 unsigned long len, struct audlpa_ion_region **region)
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530821{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530822 struct audlpa_ion_region *region_elt;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530823 int match_count = 0;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530824 *region = NULL;
825
826 /* returns physical address or zero */
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530827 list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530828 if (addr >= region_elt->vaddr &&
829 addr < region_elt->vaddr + region_elt->len &&
830 addr + len <= region_elt->vaddr + region_elt->len) {
831 /* offset since we could pass vaddr inside a registerd
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530832 * ion buffer
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530833 */
834
835 match_count++;
836 if (!*region)
837 *region = region_elt;
838 }
839 }
840
841 if (match_count > 1) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530842 MM_ERR("%s[%p]:multiple hits for vaddr %p, len %ld\n",
843 __func__, audio, addr, len);
844 list_for_each_entry(region_elt, &audio->ion_region_queue,
845 list) {
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530846 if (addr >= region_elt->vaddr &&
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530847 addr < region_elt->vaddr + region_elt->len &&
848 addr + len <= region_elt->vaddr + region_elt->len)
849 MM_ERR("\t%s[%p]:%p, %ld --> %p\n",
850 __func__, audio,
851 region_elt->vaddr,
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530852 region_elt->len,
853 (void *)region_elt->paddr);
854 }
855 }
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530856 return *region ? 0 : -1;
857}
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530858static unsigned long audlpa_ion_fixup(struct audio *audio, void *addr,
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530859 unsigned long len, int ref_up)
860{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530861 struct audlpa_ion_region *region;
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530862 unsigned long paddr;
863 int ret;
864
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530865 ret = audlpa_ion_lookup_vaddr(audio, addr, len, &region);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530866 if (ret) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530867 MM_ERR("%s[%p]:lookup (%p, %ld) failed\n",
868 __func__, audio, addr, len);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530869 return 0;
870 }
871 if (ref_up)
872 region->ref_cnt++;
873 else
874 region->ref_cnt--;
875 MM_DBG("found region %p ref_cnt %d\n", region, region->ref_cnt);
876 paddr = region->paddr + (addr - region->vaddr);
877 return paddr;
878}
879
880/* audio -> lock must be held at this point */
881static int audlpa_aio_buf_add(struct audio *audio, unsigned dir,
882 void __user *arg)
883{
884 unsigned long flags;
885 struct audpcm_buffer_node *buf_node;
886
887 buf_node = kmalloc(sizeof(*buf_node), GFP_KERNEL);
888
889 if (!buf_node)
890 return -ENOMEM;
891
892 if (copy_from_user(&buf_node->buf, arg, sizeof(buf_node->buf))) {
893 kfree(buf_node);
894 return -EFAULT;
895 }
896
897 MM_DBG("node %p dir %x buf_addr %p buf_len %d data_len"
898 "%d\n", buf_node, dir,
899 buf_node->buf.buf_addr, buf_node->buf.buf_len,
900 buf_node->buf.data_len);
901
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530902 buf_node->paddr = audlpa_ion_fixup(
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530903 audio, buf_node->buf.buf_addr,
904 buf_node->buf.buf_len, 1);
Sidipotu Ashok0a690212012-02-21 17:18:53 +0530905 if (dir) {
906 /* write */
907 if (!buf_node->paddr ||
908 (buf_node->paddr & 0x1) ||
909 (buf_node->buf.data_len & 0x1)) {
910 kfree(buf_node);
911 return -EINVAL;
912 }
913 spin_lock_irqsave(&audio->dsp_lock, flags);
914 list_add_tail(&buf_node->list, &audio->out_queue);
915 spin_unlock_irqrestore(&audio->dsp_lock, flags);
916 audpcm_async_send_data(audio, 0);
917 }
918 MM_DBG("Add buf_node %p paddr %lx\n", buf_node, buf_node->paddr);
919
920 return 0;
921}
922
923static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
924{
925 struct audio *audio = file->private_data;
926 int rc = 0;
927
928 MM_DBG("cmd = %d\n", cmd);
929
930 if (cmd == AUDIO_GET_STATS) {
931 struct msm_audio_stats stats;
932 stats.byte_count = audpp_avsync_byte_count(audio->dec_id);
933 stats.sample_count = audpp_avsync_sample_count(audio->dec_id);
934 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
935 return -EFAULT;
936 return 0;
937 }
938 if (cmd == AUDIO_SET_VOLUME) {
939 unsigned long flags;
940 spin_lock_irqsave(&audio->dsp_lock, flags);
941
942 audio->volume = MSM_VOLUME_STEP * arg;
943 audio->volume /= MSM_VOLUME_FACTOR;
944
945 if (audio->volume > MSM_MAX_VOLUME)
946 audio->volume = MSM_MAX_VOLUME;
947
948 if (audio->running)
949 audpp_set_volume_and_pan(audio->dec_id,
950 audio->volume, 0);
951 spin_unlock_irqrestore(&audio->dsp_lock, flags);
952 return 0;
953 }
954 if (cmd == AUDIO_GET_EVENT) {
955 MM_DBG("AUDIO_GET_EVENT\n");
956 if (mutex_trylock(&audio->get_event_lock)) {
957 rc = audpcm_process_event_req(audio,
958 (void __user *) arg);
959 mutex_unlock(&audio->get_event_lock);
960 } else
961 rc = -EBUSY;
962 return rc;
963 }
964
965 if (cmd == AUDIO_ABORT_GET_EVENT) {
966 audio->event_abort = 1;
967 wake_up(&audio->event_wait);
968 return 0;
969 }
970
971 mutex_lock(&audio->lock);
972 switch (cmd) {
973 case AUDIO_START:
974 MM_DBG("AUDIO_START\n");
975 rc = audio_enable(audio);
976 if (!rc) {
977 rc = wait_event_interruptible_timeout(audio->wait,
978 audio->dec_state != MSM_AUD_DECODER_STATE_NONE,
979 msecs_to_jiffies(MSM_AUD_DECODER_WAIT_MS));
980 MM_INFO("dec_state %d rc = %d\n", audio->dec_state, rc);
981
982 if (audio->dec_state != MSM_AUD_DECODER_STATE_SUCCESS)
983 rc = -ENODEV;
984 else
985 rc = 0;
986 }
987 break;
988 case AUDIO_STOP:
989 MM_DBG("AUDIO_STOP\n");
990 rc = audio_disable(audio);
991 audio_ioport_reset(audio);
992 audio->stopped = 0;
993 break;
994 case AUDIO_FLUSH:
995 MM_DBG("AUDIO_FLUSH\n");
996 audio->wflush = 1;
997 audio_ioport_reset(audio);
998 if (audio->running) {
999 audpp_flush(audio->dec_id);
1000 rc = wait_event_interruptible(audio->write_wait,
1001 !audio->wflush);
1002 if (rc < 0) {
1003 MM_ERR("AUDIO_FLUSH interrupted\n");
1004 rc = -EINTR;
1005 }
1006 } else {
1007 audio->wflush = 0;
1008 }
1009 break;
1010
1011 case AUDIO_SET_CONFIG: {
1012 struct msm_audio_config config;
1013 if (copy_from_user(&config, (void *) arg, sizeof(config))) {
1014 rc = -EFAULT;
1015 break;
1016 }
1017 if (config.channel_count == 1) {
1018 config.channel_count = AUDPP_CMD_PCM_INTF_MONO_V;
1019 } else if (config.channel_count == 2) {
1020 config.channel_count = AUDPP_CMD_PCM_INTF_STEREO_V;
1021 } else {
1022 rc = -EINVAL;
1023 break;
1024 }
1025 if (config.bits == 8)
1026 config.bits = AUDPP_CMD_WAV_PCM_WIDTH_8;
1027 else if (config.bits == 16)
1028 config.bits = AUDPP_CMD_WAV_PCM_WIDTH_16;
1029 else {
1030 rc = -EINVAL;
1031 break;
1032 }
1033 audio->out_sample_rate = config.sample_rate;
1034 audio->out_channel_mode = config.channel_count;
1035 audio->out_bits = config.bits;
1036 audio->buffer_count = config.buffer_count;
1037 audio->buffer_size = config.buffer_size;
1038 MM_DBG("AUDIO_SET_CONFIG\n");
1039 break;
1040 }
1041 case AUDIO_GET_CONFIG: {
1042 struct msm_audio_config config;
1043 config.buffer_count = audio->buffer_count;
1044 config.buffer_size = audio->buffer_size;
1045 config.sample_rate = audio->out_sample_rate;
1046 if (audio->out_channel_mode == AUDPP_CMD_PCM_INTF_MONO_V)
1047 config.channel_count = 1;
1048 else
1049 config.channel_count = 2;
1050 if (audio->out_bits == AUDPP_CMD_WAV_PCM_WIDTH_8)
1051 config.bits = 8;
1052 else if (audio->out_bits == AUDPP_CMD_WAV_PCM_WIDTH_16)
1053 config.bits = 16;
1054 else
1055 config.bits = 16;
1056 config.unused[0] = 0;
1057 config.unused[1] = 0;
1058
1059 if (copy_to_user((void *) arg, &config, sizeof(config)))
1060 rc = -EFAULT;
1061 else
1062 rc = 0;
1063 MM_DBG("AUDIO_GET_CONFIG\n");
1064 break;
1065 }
1066
1067
1068 case AUDIO_PAUSE:
1069 MM_DBG("AUDIO_PAUSE %ld\n", arg);
1070 rc = audpp_pause(audio->dec_id, (int) arg);
1071 break;
1072
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301073 case AUDIO_REGISTER_ION: {
1074 struct msm_audio_ion_info info;
1075 MM_ERR("AUDIO_REGISTER_ION\n");
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301076 if (copy_from_user(&info, (void *) arg, sizeof(info)))
1077 rc = -EFAULT;
1078 else
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301079 rc = audlpa_ion_add(audio, &info);
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301080 break;
1081 }
1082
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301083 case AUDIO_DEREGISTER_ION: {
1084 struct msm_audio_ion_info info;
1085 MM_ERR("AUDIO_DEREGISTER_ION\n");
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301086 if (copy_from_user(&info, (void *) arg, sizeof(info)))
1087 rc = -EFAULT;
1088 else
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301089 rc = audlpa_ion_remove(audio, &info);
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301090 break;
1091 }
1092
1093 case AUDIO_ASYNC_WRITE:
1094 if (audio->drv_status & ADRV_STATUS_FSYNC)
1095 rc = -EBUSY;
1096 else
1097 rc = audlpa_aio_buf_add(audio, 1, (void __user *) arg);
1098 break;
1099
1100 case AUDIO_ASYNC_READ:
1101 MM_ERR("AUDIO_ASYNC_READ not supported\n");
1102 rc = -EPERM;
1103 break;
1104
1105 default:
1106 rc = -EINVAL;
1107 }
1108 mutex_unlock(&audio->lock);
1109 return rc;
1110}
1111
1112/* Only useful in tunnel-mode */
1113int audlpa_async_fsync(struct audio *audio)
1114{
1115 int rc = 0;
1116
1117 MM_DBG("\n"); /* Macro prints the file name and function */
1118
1119 /* Blocking client sends more data */
1120 mutex_lock(&audio->lock);
1121 audio->drv_status |= ADRV_STATUS_FSYNC;
1122 mutex_unlock(&audio->lock);
1123
1124 mutex_lock(&audio->write_lock);
1125 /* pcm dmamiss message is sent continously
1126 * when decoder is starved so no race
1127 * condition concern
1128 */
1129 audio->teos = 0;
1130
1131 rc = wait_event_interruptible(audio->write_wait,
1132 (audio->teos && audio->out_needed &&
1133 list_empty(&audio->out_queue))
1134 || audio->wflush || audio->stopped);
1135
1136 if (audio->stopped || audio->wflush)
1137 rc = -EBUSY;
1138
1139 mutex_unlock(&audio->write_lock);
1140 mutex_lock(&audio->lock);
1141 audio->drv_status &= ~ADRV_STATUS_FSYNC;
1142 mutex_unlock(&audio->lock);
1143
1144 return rc;
1145}
1146
1147int audlpa_sync_fsync(struct audio *audio)
1148{
1149 struct buffer *frame;
1150 int rc = 0;
1151
1152 MM_DBG("\n"); /* Macro prints the file name and function */
1153
1154 mutex_lock(&audio->write_lock);
1155
1156 rc = wait_event_interruptible(audio->write_wait,
1157 (!audio->out[0].used &&
1158 !audio->out[1].used &&
1159 audio->out_needed) || audio->wflush);
1160
1161 if (rc < 0)
1162 goto done;
1163 else if (audio->wflush) {
1164 rc = -EBUSY;
1165 goto done;
1166 }
1167
1168 if (audio->reserved) {
1169 MM_DBG("send reserved byte\n");
1170 frame = audio->out + audio->out_tail;
1171 ((char *) frame->data)[0] = audio->rsv_byte;
1172 ((char *) frame->data)[1] = 0;
1173 frame->used = 2;
1174 audpcm_async_send_data(audio, 0);
1175
1176 rc = wait_event_interruptible(audio->write_wait,
1177 (!audio->out[0].used &&
1178 !audio->out[1].used &&
1179 audio->out_needed) || audio->wflush);
1180
1181 if (rc < 0)
1182 goto done;
1183 else if (audio->wflush) {
1184 rc = -EBUSY;
1185 goto done;
1186 }
1187 }
1188
1189 /* pcm dmamiss message is sent continously
1190 * when decoder is starved so no race
1191 * condition concern
1192 */
1193 audio->teos = 0;
1194
1195 rc = wait_event_interruptible(audio->write_wait,
1196 audio->teos || audio->wflush);
1197
1198 if (audio->wflush)
1199 rc = -EBUSY;
1200
1201done:
1202 mutex_unlock(&audio->write_lock);
1203 return rc;
1204}
1205
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301206int audlpa_fsync(struct file *file, loff_t a, loff_t b,
1207 int datasync)
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301208{
1209 struct audio *audio = file->private_data;
1210
1211 if (!audio->running)
1212 return -EINVAL;
1213
1214 return audlpa_async_fsync(audio);
1215}
1216
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301217static void audpcm_reset_ion_region(struct audio *audio)
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301218{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301219 struct audlpa_ion_region *region;
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301220 struct list_head *ptr, *next;
1221
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301222 list_for_each_safe(ptr, next, &audio->ion_region_queue) {
1223 region = list_entry(ptr, struct audlpa_ion_region, list);
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301224 list_del(&region->list);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301225 ion_unmap_kernel(audio->client, region->handle);
1226 ion_free(audio->client, region->handle);
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301227 kfree(region);
1228 }
1229
1230 return;
1231}
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301232static int audio_release(struct inode *inode, struct file *file)
1233{
1234 struct audio *audio = file->private_data;
1235
1236 MM_DBG("audio instance 0x%08x freeing\n", (int)audio);
1237 mutex_lock(&audio->lock);
1238 audio_disable(audio);
1239 if (audio->rmt_resource_released == 0)
1240 rmt_put_resource(audio);
1241 audpcm_async_flush(audio);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301242 audpcm_reset_ion_region(audio);
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301243
1244 msm_adsp_put(audio->audplay);
1245 audpp_adec_free(audio->dec_id);
1246#ifdef CONFIG_HAS_EARLYSUSPEND
1247 unregister_early_suspend(&audio->suspend_ctl.node);
1248#endif
1249 audio->opened = 0;
1250 audio->event_abort = 1;
1251 wake_up(&audio->event_wait);
1252 audpcm_reset_event_queue(audio);
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301253 mutex_unlock(&audio->lock);
1254#ifdef CONFIG_DEBUG_FS
1255 if (audio->dentry)
1256 debugfs_remove(audio->dentry);
1257#endif
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301258 ion_client_destroy(audio->client);
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301259 kfree(audio);
1260 return 0;
1261}
1262
1263static void audpcm_post_event(struct audio *audio, int type,
1264 union msm_audio_event_payload payload)
1265{
1266 struct audpcm_event *e_node = NULL;
1267 unsigned long flags;
1268
1269 spin_lock_irqsave(&audio->event_queue_lock, flags);
1270
1271 if (!list_empty(&audio->free_event_queue)) {
1272 e_node = list_first_entry(&audio->free_event_queue,
1273 struct audpcm_event, list);
1274 list_del(&e_node->list);
1275 } else {
1276 e_node = kmalloc(sizeof(struct audpcm_event), GFP_ATOMIC);
1277 if (!e_node) {
1278 MM_ERR("No mem to post event %d\n", type);
1279 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
1280 return;
1281 }
1282 }
1283
1284 e_node->event_type = type;
1285 e_node->payload = payload;
1286
1287 list_add_tail(&e_node->list, &audio->event_queue);
1288 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
1289 wake_up(&audio->event_wait);
1290}
1291
1292#ifdef CONFIG_HAS_EARLYSUSPEND
1293static void audpcm_suspend(struct early_suspend *h)
1294{
1295 struct audpcm_suspend_ctl *ctl =
1296 container_of(h, struct audpcm_suspend_ctl, node);
1297 union msm_audio_event_payload payload;
1298
1299 MM_DBG("\n"); /* Macro prints the file name and function */
1300 audpcm_post_event(ctl->audio, AUDIO_EVENT_SUSPEND, payload);
1301}
1302
1303static void audpcm_resume(struct early_suspend *h)
1304{
1305 struct audpcm_suspend_ctl *ctl =
1306 container_of(h, struct audpcm_suspend_ctl, node);
1307 union msm_audio_event_payload payload;
1308
1309 MM_DBG("\n"); /* Macro prints the file name and function */
1310 audpcm_post_event(ctl->audio, AUDIO_EVENT_RESUME, payload);
1311}
1312#endif
1313
1314#ifdef CONFIG_DEBUG_FS
1315static ssize_t audpcm_debug_open(struct inode *inode, struct file *file)
1316{
1317 file->private_data = inode->i_private;
1318 return 0;
1319}
1320
1321static ssize_t audpcm_debug_read(struct file *file, char __user *buf,
1322 size_t count, loff_t *ppos)
1323{
1324 const int debug_bufmax = 4096;
1325 static char buffer[4096];
1326 int n = 0;
1327 struct audio *audio = file->private_data;
1328
1329 mutex_lock(&audio->lock);
1330 n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
1331 n += scnprintf(buffer + n, debug_bufmax - n,
1332 "enabled %d\n", audio->enabled);
1333 n += scnprintf(buffer + n, debug_bufmax - n,
1334 "stopped %d\n", audio->stopped);
1335 n += scnprintf(buffer + n, debug_bufmax - n,
1336 "out_buf_sz %d\n", audio->out[0].size);
1337 n += scnprintf(buffer + n, debug_bufmax - n,
1338 "volume %lx\n", audio->volume);
1339 n += scnprintf(buffer + n, debug_bufmax - n,
1340 "sample rate %d\n", audio->out_sample_rate);
1341 n += scnprintf(buffer + n, debug_bufmax - n,
1342 "channel mode %d\n", audio->out_channel_mode);
1343 mutex_unlock(&audio->lock);
1344 /* Following variables are only useful for debugging when
1345 * when playback halts unexpectedly. Thus, no mutual exclusion
1346 * enforced
1347 */
1348 n += scnprintf(buffer + n, debug_bufmax - n,
1349 "wflush %d\n", audio->wflush);
1350 n += scnprintf(buffer + n, debug_bufmax - n,
1351 "running %d\n", audio->running);
1352 n += scnprintf(buffer + n, debug_bufmax - n,
1353 "dec state %d\n", audio->dec_state);
1354 n += scnprintf(buffer + n, debug_bufmax - n,
1355 "out_needed %d\n", audio->out_needed);
1356 n += scnprintf(buffer + n, debug_bufmax - n,
1357 "out_head %d\n", audio->out_head);
1358 n += scnprintf(buffer + n, debug_bufmax - n,
1359 "out_tail %d\n", audio->out_tail);
1360 n += scnprintf(buffer + n, debug_bufmax - n,
1361 "out[0].used %d\n", audio->out[0].used);
1362 n += scnprintf(buffer + n, debug_bufmax - n,
1363 "out[1].used %d\n", audio->out[1].used);
1364 buffer[n] = 0;
1365 return simple_read_from_buffer(buf, count, ppos, buffer, n);
1366}
1367
1368static const struct file_operations audpcm_debug_fops = {
1369 .read = audpcm_debug_read,
1370 .open = audpcm_debug_open,
1371};
1372#endif
1373
1374static int audio_open(struct inode *inode, struct file *file)
1375{
1376 struct audio *audio = NULL;
1377 int rc, i, dec_attrb, decid;
1378 struct audpcm_event *e_node = NULL;
1379
1380#ifdef CONFIG_DEBUG_FS
1381 /* 4 bytes represents decoder number, 1 byte for terminate string */
1382 char name[sizeof "msm_lpa_" + 5];
1383#endif
1384
1385 /* Allocate audio instance, set to zero */
1386 audio = kzalloc(sizeof(struct audio), GFP_KERNEL);
1387 if (!audio) {
1388 MM_ERR("no memory to allocate audio instance\n");
1389 rc = -ENOMEM;
1390 goto done;
1391 }
1392 MM_DBG("audio instance 0x%08x created\n", (int)audio);
1393
1394 /* Allocate the decoder */
1395 dec_attrb = AUDDEC_DEC_PCM;
1396 if (file->f_mode & FMODE_READ) {
1397 MM_ERR("Non-Tunneled mode not supported\n");
1398 rc = -EPERM;
1399 kfree(audio);
1400 goto done;
1401 } else
1402 dec_attrb |= MSM_AUD_MODE_TUNNEL;
1403
1404 decid = audpp_adec_alloc(dec_attrb, &audio->module_name,
1405 &audio->queue_id);
1406 if (decid < 0) {
1407 MM_ERR("No free decoder available\n");
1408 rc = -ENODEV;
1409 MM_DBG("audio instance 0x%08x freeing\n", (int)audio);
1410 kfree(audio);
1411 goto done;
1412 }
1413 audio->dec_id = decid & MSM_AUD_DECODER_MASK;
1414
1415 audio->buffer_size = BUFSZ;
1416 audio->buffer_count = MAX_BUF;
1417 rc = audmgr_open(&audio->audmgr);
1418 if (rc)
1419 goto err;
1420
1421 rc = msm_adsp_get(audio->module_name, &audio->audplay,
1422 &audlpadec_adsp_ops, audio);
1423 if (rc) {
1424 MM_ERR("failed to get %s module\n", audio->module_name);
1425 audmgr_close(&audio->audmgr);
1426 goto err;
1427 }
1428
1429 rc = rmt_get_resource(audio);
1430 if (rc) {
1431 MM_ERR("ADSP resources are not available for PCM session");
1432 audmgr_close(&audio->audmgr);
1433 msm_adsp_put(audio->audplay);
1434 goto err;
1435 }
1436
1437 /* Initialize all locks of audio instance */
1438 mutex_init(&audio->lock);
1439 mutex_init(&audio->write_lock);
1440 mutex_init(&audio->get_event_lock);
1441 spin_lock_init(&audio->dsp_lock);
1442 init_waitqueue_head(&audio->write_wait);
1443 INIT_LIST_HEAD(&audio->out_queue);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301444 INIT_LIST_HEAD(&audio->ion_region_queue);
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301445 INIT_LIST_HEAD(&audio->free_event_queue);
1446 INIT_LIST_HEAD(&audio->event_queue);
1447 init_waitqueue_head(&audio->wait);
1448 init_waitqueue_head(&audio->event_wait);
1449 spin_lock_init(&audio->event_queue_lock);
1450
1451 audio->out_sample_rate = 44100;
1452 audio->out_channel_mode = AUDPP_CMD_PCM_INTF_STEREO_V;
1453 audio->out_bits = AUDPP_CMD_WAV_PCM_WIDTH_16;
1454 audio->volume = 0x2000;
1455 audpcm_async_flush(audio);
1456
1457 file->private_data = audio;
1458 audio->opened = 1;
1459
1460#ifdef CONFIG_DEBUG_FS
1461 snprintf(name, sizeof name, "msm_pcm_lp_dec_%04x", audio->dec_id);
1462 audio->dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
1463 NULL, (void *) audio, &audpcm_debug_fops);
1464
1465 if (IS_ERR(audio->dentry))
1466 MM_DBG("debugfs_create_file failed\n");
1467#endif
1468#ifdef CONFIG_HAS_EARLYSUSPEND
1469 audio->suspend_ctl.node.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
1470 audio->suspend_ctl.node.resume = audpcm_resume;
1471 audio->suspend_ctl.node.suspend = audpcm_suspend;
1472 audio->suspend_ctl.audio = audio;
1473 register_early_suspend(&audio->suspend_ctl.node);
1474#endif
1475 for (i = 0; i < AUDPCM_EVENT_NUM; i++) {
1476 e_node = kmalloc(sizeof(struct audpcm_event), GFP_KERNEL);
1477 if (e_node)
1478 list_add_tail(&e_node->list, &audio->free_event_queue);
1479 else {
1480 MM_ERR("event pkt alloc failed\n");
1481 break;
1482 }
1483 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301484
1485 audio->client = msm_ion_client_create(UINT_MAX, "Audio_LPA_Client");
1486 if (IS_ERR_OR_NULL(audio->client)) {
1487 pr_err("Unable to create ION client\n");
1488 goto err;
1489 }
1490 MM_DBG("Ion client created\n");
1491
Sidipotu Ashok0a690212012-02-21 17:18:53 +05301492done:
1493 return rc;
1494err:
1495 audpp_adec_free(audio->dec_id);
1496 MM_DBG("audio instance 0x%08x freeing\n", (int)audio);
1497 kfree(audio);
1498 return rc;
1499}
1500
1501static const struct file_operations audio_pcm_lp_fops = {
1502 .owner = THIS_MODULE,
1503 .open = audio_open,
1504 .release = audio_release,
1505 .unlocked_ioctl = audio_ioctl,
1506 .fsync = audlpa_fsync,
1507};
1508
1509struct miscdevice audio_lpa_misc = {
1510 .minor = MISC_DYNAMIC_MINOR,
1511 .name = "msm_pcm_lp_dec",
1512 .fops = &audio_pcm_lp_fops,
1513};
1514
1515static int __init audio_init(void)
1516{
1517 return misc_register(&audio_lpa_misc);
1518}
1519
1520device_initcall(audio_init);