blob: 3eb72c86dbe17a443bec91877c2a2cb61f91ae3d [file] [log] [blame]
Santosh Mardi0be3b8e2011-07-06 10:00:21 +05301
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002/* audio_pcm.c - pcm audio decoder driver
3 *
Manish Dewangana4f1df02012-02-08 17:06:54 +05304 * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07005 *
6 * Based on the mp3 decoder driver in arch/arm/mach-msm/qdsp5/audio_mp3.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
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053027#include <asm/atomic.h>
28#include <asm/ioctls.h>
29
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070030#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>
40#include <linux/list.h>
Mitchel Humpherys1da6ebe2012-09-06 10:15:56 -070041#include <linux/msm_ion.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070042#include <linux/slab.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043#include <linux/msm_audio.h>
44
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070045
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053046#include <mach/msm_adsp.h>
47#include <mach/iommu.h>
48#include <mach/iommu_domains.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070049#include <mach/qdsp5/qdsp5audppcmdi.h>
50#include <mach/qdsp5/qdsp5audppmsg.h>
Manish Dewanganfa8a6b62012-07-09 16:23:27 +053051#include <mach/qdsp5/qdsp5audpp.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070052#include <mach/qdsp5/qdsp5audplaycmdi.h>
53#include <mach/qdsp5/qdsp5audplaymsg.h>
54#include <mach/qdsp5/qdsp5rmtcmdi.h>
55#include <mach/debug_mm.h>
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053056#include <linux/memory_alloc.h>
57#include <mach/msm_memtypes.h>
58
59#include "audmgr.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070060
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/* Size must be power of 2 */
70#define BUFSZ_MAX 32768
71#define BUFSZ_MIN 4096
72#define DMASZ_MAX (BUFSZ_MAX * 2)
73#define DMASZ_MIN (BUFSZ_MIN * 2)
74
75#define AUDDEC_DEC_PCM 0
76
77/* Decoder status received from AUDPPTASK */
78#define AUDPP_DEC_STATUS_SLEEP 0
79#define AUDPP_DEC_STATUS_INIT 1
80#define AUDPP_DEC_STATUS_CFG 2
81#define AUDPP_DEC_STATUS_PLAY 3
82
83#define AUDPCM_EVENT_NUM 10 /* Default number of pre-allocated event packets */
84
85#define __CONTAINS(r, v, l) ({ \
86 typeof(r) __r = r; \
87 typeof(v) __v = v; \
88 typeof(v) __e = __v + l; \
89 int res = ((__v >= __r->vaddr) && \
90 (__e <= __r->vaddr + __r->len)); \
91 res; \
92})
93
94#define CONTAINS(r1, r2) ({ \
95 typeof(r2) __r2 = r2; \
96 __CONTAINS(r1, __r2->vaddr, __r2->len); \
97})
98
99#define IN_RANGE(r, v) ({ \
100 typeof(r) __r = r; \
101 typeof(v) __vv = v; \
102 int res = ((__vv >= __r->vaddr) && \
103 (__vv < (__r->vaddr + __r->len))); \
104 res; \
105})
106
107#define OVERLAPS(r1, r2) ({ \
108 typeof(r1) __r1 = r1; \
109 typeof(r2) __r2 = r2; \
110 typeof(__r2->vaddr) __v = __r2->vaddr; \
111 typeof(__v) __e = __v + __r2->len - 1; \
112 int res = (IN_RANGE(__r1, __v) || IN_RANGE(__r1, __e)); \
113 res; \
114})
115
116struct audio;
117
118struct buffer {
119 void *data;
120 unsigned size;
121 unsigned used; /* Input usage actual DSP produced PCM size */
122 unsigned addr;
123};
124
125#ifdef CONFIG_HAS_EARLYSUSPEND
126struct audpcm_suspend_ctl {
127 struct early_suspend node;
128 struct audio *audio;
129};
130#endif
131
132struct audpcm_event {
133 struct list_head list;
134 int event_type;
135 union msm_audio_event_payload payload;
136};
137
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530138struct audpcm_ion_region {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700139 struct list_head list;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530140 struct ion_handle *handle;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141 int fd;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700142 void *vaddr;
143 unsigned long paddr;
144 unsigned long kvaddr;
145 unsigned long len;
146 unsigned ref_cnt;
147};
148
149struct audpcm_buffer_node {
150 struct list_head list;
151 struct msm_audio_aio_buf buf;
152 unsigned long paddr;
153};
154
155struct audpcm_drv_operations {
156 void (*send_data)(struct audio *, unsigned);
157 void (*out_flush)(struct audio *);
158 int (*fsync)(struct audio *);
159};
160
161struct audio {
162 struct buffer out[2];
163
164 spinlock_t dsp_lock;
165
166 uint8_t out_head;
167 uint8_t out_tail;
168 uint8_t out_needed; /* number of buffers the dsp is waiting for */
169 unsigned out_dma_sz;
170 struct list_head out_queue; /* queue to retain output buffers */
171 atomic_t out_bytes;
172
173 struct mutex lock;
174 struct mutex write_lock;
175 wait_queue_head_t write_wait;
176
177 struct msm_adsp_module *audplay;
178
179 /* configuration to use on next enable */
180 uint32_t out_sample_rate;
181 uint32_t out_channel_mode;
182 uint32_t out_bits; /* bits per sample */
183
184 struct audmgr audmgr;
185
186 /* data allocated for various buffers */
187 char *data;
188 int32_t phys;
Laura Abbott35111d32012-04-27 18:41:48 -0700189 void *map_v_write;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700190
191 uint32_t drv_status;
192 int wflush; /* Write flush */
193 int opened;
194 int enabled;
195 int running;
196 int stopped; /* set when stopped, cleared on flush */
197 int teos; /* valid only if tunnel mode & no data left for decoder */
198 int rmt_resource_released;
199 enum msm_aud_decoder_state dec_state; /* Represents decoder state */
200 int reserved; /* A byte is being reserved */
201 char rsv_byte; /* Handle odd length user data */
202
203 const char *module_name;
204 unsigned queue_id;
205
206 unsigned volume;
207
208 uint16_t dec_id;
209
210#ifdef CONFIG_HAS_EARLYSUSPEND
211 struct audpcm_suspend_ctl suspend_ctl;
212#endif
213
214#ifdef CONFIG_DEBUG_FS
215 struct dentry *dentry;
216#endif
217 wait_queue_head_t wait;
218 struct list_head free_event_queue;
219 struct list_head event_queue;
220 wait_queue_head_t event_wait;
221 spinlock_t event_queue_lock;
222 struct mutex get_event_lock;
223 int event_abort;
224
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530225 struct list_head ion_region_queue;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700226 struct audpcm_drv_operations drv_ops;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530227 struct ion_client *client;
228 struct ion_handle *output_buff_handle;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700229};
230
231static int auddec_dsp_config(struct audio *audio, int enable);
232static void audpp_cmd_cfg_adec_params(struct audio *audio);
233static void audplay_send_data(struct audio *audio, unsigned needed);
234static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
235static void audpcm_post_event(struct audio *audio, int type,
236 union msm_audio_event_payload payload);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530237static unsigned long audpcm_ion_fixup(struct audio *audio, void *addr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700238 unsigned long len, int ref_up);
239
240static int rmt_put_resource(struct audio *audio)
241{
242 struct aud_codec_config_cmd cmd;
243 unsigned short client_idx;
244
245 cmd.cmd_id = RM_CMD_AUD_CODEC_CFG;
246 cmd.client_id = RM_AUD_CLIENT_ID;
247 cmd.task_id = audio->dec_id;
248 cmd.enable = RMT_DISABLE;
249 cmd.dec_type = AUDDEC_DEC_PCM;
250 client_idx = ((cmd.client_id << 8) | cmd.task_id);
251
252 return put_adsp_resource(client_idx, &cmd, sizeof(cmd));
253}
254
255static int rmt_get_resource(struct audio *audio)
256{
257 struct aud_codec_config_cmd cmd;
258 unsigned short client_idx;
259
260 cmd.cmd_id = RM_CMD_AUD_CODEC_CFG;
261 cmd.client_id = RM_AUD_CLIENT_ID;
262 cmd.task_id = audio->dec_id;
263 cmd.enable = RMT_ENABLE;
264 cmd.dec_type = AUDDEC_DEC_PCM;
265 client_idx = ((cmd.client_id << 8) | cmd.task_id);
266
267 return get_adsp_resource(client_idx, &cmd, sizeof(cmd));
268}
269
270/* must be called with audio->lock held */
271static int audio_enable(struct audio *audio)
272{
273 struct audmgr_config cfg;
274 int rc;
275
276 MM_DBG("\n"); /* Macro prints the file name and function */
277 if (audio->enabled)
278 return 0;
279
280 if (audio->rmt_resource_released == 1) {
281 audio->rmt_resource_released = 0;
282 rc = rmt_get_resource(audio);
283 if (rc) {
284 MM_ERR("ADSP resources are not available for PCM \
285 session 0x%08x on decoder: %d\n Ignoring \
286 error and going ahead with the playback\n",
287 (int)audio, audio->dec_id);
288 }
289 }
290
291 audio->dec_state = MSM_AUD_DECODER_STATE_NONE;
292 audio->out_tail = 0;
293 audio->out_needed = 0;
294
295 cfg.tx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
296 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_48000;
297 cfg.def_method = RPC_AUD_DEF_METHOD_PLAYBACK;
298 cfg.codec = RPC_AUD_DEF_CODEC_PCM;
299 cfg.snd_method = RPC_SND_METHOD_MIDI;
300
301 rc = audmgr_enable(&audio->audmgr, &cfg);
302 if (rc < 0)
303 return rc;
304
305 if (msm_adsp_enable(audio->audplay)) {
306 MM_ERR("msm_adsp_enable(audplay) failed\n");
307 audmgr_disable(&audio->audmgr);
308 return -ENODEV;
309 }
310
311 if (audpp_enable(audio->dec_id, audio_dsp_event, audio)) {
312 MM_ERR("audpp_enable() failed\n");
313 msm_adsp_disable(audio->audplay);
314 audmgr_disable(&audio->audmgr);
315 return -ENODEV;
316 }
317
318 audio->enabled = 1;
319 return 0;
320}
321
322/* must be called with audio->lock held */
323static int audio_disable(struct audio *audio)
324{
325 int rc = 0;
326 MM_DBG("\n"); /* Macro prints the file name and function */
327 if (audio->enabled) {
328 audio->enabled = 0;
329 audio->dec_state = MSM_AUD_DECODER_STATE_NONE;
330 auddec_dsp_config(audio, 0);
331 rc = wait_event_interruptible_timeout(audio->wait,
332 audio->dec_state != MSM_AUD_DECODER_STATE_NONE,
333 msecs_to_jiffies(MSM_AUD_DECODER_WAIT_MS));
334 if (rc == 0)
335 rc = -ETIMEDOUT;
336 else if (audio->dec_state != MSM_AUD_DECODER_STATE_CLOSE)
337 rc = -EFAULT;
338 else
339 rc = 0;
Manish Dewangan89a9f232012-02-09 17:14:40 +0530340 audio->stopped = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700341 wake_up(&audio->write_wait);
342 msm_adsp_disable(audio->audplay);
343 audpp_disable(audio->dec_id, audio);
344 audmgr_disable(&audio->audmgr);
345 audio->out_needed = 0;
346 rmt_put_resource(audio);
347 audio->rmt_resource_released = 1;
348 }
349 return rc;
350}
351
352/* ------------------- dsp --------------------- */
353static void audplay_dsp_event(void *data, unsigned id, size_t len,
354 void (*getevent) (void *ptr, size_t len))
355{
356 struct audio *audio = data;
357 uint32_t msg[28];
358 getevent(msg, sizeof(msg));
359
360 MM_DBG("msg_id=%x\n", id);
361
362 switch (id) {
363 case AUDPLAY_MSG_DEC_NEEDS_DATA:
364 audio->drv_ops.send_data(audio, 1);
365 break;
366 case ADSP_MESSAGE_ID:
367 MM_DBG("Received ADSP event: module enable(audplaytask)\n");
368 break;
369 default:
370 MM_ERR("unexpected message from decoder \n");
371 break;
372 }
373}
374
375static void audio_dsp_event(void *private, unsigned id, uint16_t *msg)
376{
377 struct audio *audio = private;
378
379 switch (id) {
380 case AUDPP_MSG_STATUS_MSG:{
381 unsigned status = msg[1];
382
383 switch (status) {
384 case AUDPP_DEC_STATUS_SLEEP: {
385 uint16_t reason = msg[2];
386 MM_DBG("decoder status: sleep reason = \
387 0x%04x\n", reason);
388 if ((reason == AUDPP_MSG_REASON_MEM)
389 || (reason ==
390 AUDPP_MSG_REASON_NODECODER)) {
391 audio->dec_state =
392 MSM_AUD_DECODER_STATE_FAILURE;
393 wake_up(&audio->wait);
394 } else if (reason == AUDPP_MSG_REASON_NONE) {
395 /* decoder is in disable state */
396 audio->dec_state =
397 MSM_AUD_DECODER_STATE_CLOSE;
398 wake_up(&audio->wait);
399 }
400 break;
401 }
402 case AUDPP_DEC_STATUS_INIT:
403 MM_DBG("decoder status: init\n");
404 audpp_cmd_cfg_adec_params(audio);
405 break;
406
407 case AUDPP_DEC_STATUS_CFG:
408 MM_DBG("decoder status: cfg \n");
409 break;
410 case AUDPP_DEC_STATUS_PLAY:
411 MM_DBG("decoder status: play \n");
412 audio->dec_state =
413 MSM_AUD_DECODER_STATE_SUCCESS;
414 wake_up(&audio->wait);
415 break;
416 default:
417 MM_ERR("unknown decoder status \n");
418 break;
419 }
420 break;
421 }
422 case AUDPP_MSG_CFG_MSG:
423 if (msg[0] == AUDPP_MSG_ENA_ENA) {
424 MM_DBG("CFG_MSG ENABLE\n");
425 auddec_dsp_config(audio, 1);
426 audio->out_needed = 0;
427 audio->running = 1;
428 audpp_set_volume_and_pan(audio->dec_id, audio->volume,
429 0);
430 } else if (msg[0] == AUDPP_MSG_ENA_DIS) {
431 MM_DBG("CFG_MSG DISABLE\n");
432 audio->running = 0;
433 } else {
434 MM_ERR("CFG_MSG %d?\n", msg[0]);
435 }
436 break;
437 case AUDPP_MSG_FLUSH_ACK:
438 MM_DBG("FLUSH_ACK\n");
439 audio->wflush = 0;
440 wake_up(&audio->write_wait);
441 break;
442
443 case AUDPP_MSG_PCMDMAMISSED:
444 MM_DBG("PCMDMAMISSED\n");
445 audio->teos = 1;
446 wake_up(&audio->write_wait);
447 break;
448
449 default:
450 MM_ERR("UNKNOWN (%d)\n", id);
451 }
452
453}
454
455
456struct msm_adsp_ops audpcmdec_adsp_ops = {
457 .event = audplay_dsp_event,
458};
459
460
461#define audplay_send_queue0(audio, cmd, len) \
462 msm_adsp_write(audio->audplay, audio->queue_id, \
463 cmd, len)
464
465static int auddec_dsp_config(struct audio *audio, int enable)
466{
467 u16 cfg_dec_cmd[AUDPP_CMD_CFG_DEC_TYPE_LEN / sizeof(unsigned short)];
468
469 memset(cfg_dec_cmd, 0, sizeof(cfg_dec_cmd));
470
471 cfg_dec_cmd[0] = AUDPP_CMD_CFG_DEC_TYPE;
472 if (enable)
473 cfg_dec_cmd[1 + audio->dec_id] = AUDPP_CMD_UPDATDE_CFG_DEC |
474 AUDPP_CMD_ENA_DEC_V | AUDDEC_DEC_PCM;
475 else
476 cfg_dec_cmd[1 + audio->dec_id] = AUDPP_CMD_UPDATDE_CFG_DEC |
477 AUDPP_CMD_DIS_DEC_V;
478
479 return audpp_send_queue1(&cfg_dec_cmd, sizeof(cfg_dec_cmd));
480}
481
482static void audpp_cmd_cfg_adec_params(struct audio *audio)
483{
484 audpp_cmd_cfg_adec_params_wav cmd;
485
486 memset(&cmd, 0, sizeof(cmd));
487 cmd.common.cmd_id = AUDPP_CMD_CFG_ADEC_PARAMS;
488 cmd.common.length = AUDPP_CMD_CFG_ADEC_PARAMS_WAV_LEN;
489 cmd.common.dec_id = audio->dec_id;
490 cmd.common.input_sampling_frequency = audio->out_sample_rate;
491 cmd.stereo_cfg = audio->out_channel_mode;
492 cmd.pcm_width = audio->out_bits;
493 cmd.sign = 0;
494 audpp_send_queue2(&cmd, sizeof(cmd));
495}
496
497static int audplay_dsp_send_data_avail(struct audio *audio,
498 unsigned idx, unsigned len)
499{
500 audplay_cmd_bitstream_data_avail cmd;
501
502 cmd.cmd_id = AUDPLAY_CMD_BITSTREAM_DATA_AVAIL;
503 cmd.decoder_id = audio->dec_id;
504 cmd.buf_ptr = audio->out[idx].addr;
505 cmd.buf_size = len/2;
506 cmd.partition_number = 0;
507 /* complete writes to the input buffer */
508 wmb();
509 return audplay_send_queue0(audio, &cmd, sizeof(cmd));
510}
511
512static void audpcm_async_send_data(struct audio *audio, unsigned needed)
513{
514 unsigned long flags;
515
516 if (!audio->running)
517 return;
518
519 spin_lock_irqsave(&audio->dsp_lock, flags);
520
521 if (needed && !audio->wflush) {
522 audio->out_needed = 1;
523 if (audio->drv_status & ADRV_STATUS_OBUF_GIVEN) {
524 /* pop one node out of queue */
525 union msm_audio_event_payload payload;
526 struct audpcm_buffer_node *used_buf;
527
528 MM_DBG("consumed\n");
529
530 BUG_ON(list_empty(&audio->out_queue));
531 used_buf = list_first_entry(&audio->out_queue,
532 struct audpcm_buffer_node, list);
533 list_del(&used_buf->list);
534 payload.aio_buf = used_buf->buf;
535 audpcm_post_event(audio, AUDIO_EVENT_WRITE_DONE,
536 payload);
537 kfree(used_buf);
538 audio->drv_status &= ~ADRV_STATUS_OBUF_GIVEN;
539 }
540 }
541 if (audio->out_needed) {
542 struct audpcm_buffer_node *next_buf;
543 audplay_cmd_bitstream_data_avail cmd;
544 if (!list_empty(&audio->out_queue)) {
545 next_buf = list_first_entry(&audio->out_queue,
546 struct audpcm_buffer_node, list);
547 MM_DBG("next_buf %p\n", next_buf);
548 if (next_buf) {
549 MM_DBG("next buf phy %lx len %d\n",
550 next_buf->paddr, next_buf->buf.data_len);
551
552 cmd.cmd_id = AUDPLAY_CMD_BITSTREAM_DATA_AVAIL;
553 if (next_buf->buf.data_len)
554 cmd.decoder_id = audio->dec_id;
555 else {
556 cmd.decoder_id = -1;
557 MM_DBG("input EOS signaled\n");
558 }
559 cmd.buf_ptr = (unsigned) next_buf->paddr;
560 cmd.buf_size = next_buf->buf.data_len >> 1;
561 cmd.partition_number = 0;
562 /* complete writes to the input buffer */
563 wmb();
564 audplay_send_queue0(audio, &cmd, sizeof(cmd));
565 audio->out_needed = 0;
566 audio->drv_status |= ADRV_STATUS_OBUF_GIVEN;
567 }
568 }
569 }
570 spin_unlock_irqrestore(&audio->dsp_lock, flags);
571}
572
573static void audplay_send_data(struct audio *audio, unsigned needed)
574{
575 struct buffer *frame;
576 unsigned long flags;
577
578 if (!audio->running)
579 return;
580
581 spin_lock_irqsave(&audio->dsp_lock, flags);
582
583 if (needed && !audio->wflush) {
584 /* We were called from the callback because the DSP
585 * requested more data. Note that the DSP does want
586 * more data, and if a buffer was in-flight, mark it
587 * as available (since the DSP must now be done with
588 * it).
589 */
590 audio->out_needed = 1;
591 frame = audio->out + audio->out_tail;
592 if (frame->used == 0xffffffff) {
593 MM_DBG("frame %d free\n", audio->out_tail);
594 frame->used = 0;
595 audio->out_tail ^= 1;
596 wake_up(&audio->write_wait);
597 }
598 }
599
600 if (audio->out_needed) {
601 /* If the DSP currently wants data and we have a
602 * buffer available, we will send it and reset
603 * the needed flag. We'll mark the buffer as in-flight
604 * so that it won't be recycled until the next buffer
605 * is requested
606 */
607
608 frame = audio->out + audio->out_tail;
609 if (frame->used) {
610 BUG_ON(frame->used == 0xffffffff);
611 MM_DBG("frame %d busy\n", audio->out_tail);
612 audplay_dsp_send_data_avail(audio, audio->out_tail,
613 frame->used);
614 frame->used = 0xffffffff;
615 audio->out_needed = 0;
616 }
617 }
618 spin_unlock_irqrestore(&audio->dsp_lock, flags);
619}
620
621/* ------------------- device --------------------- */
622static void audpcm_async_flush(struct audio *audio)
623{
624 struct audpcm_buffer_node *buf_node;
625 struct list_head *ptr, *next;
626 union msm_audio_event_payload payload;
627
628 MM_DBG("\n"); /* Macro prints the file name and function */
629 list_for_each_safe(ptr, next, &audio->out_queue) {
630 buf_node = list_entry(ptr, struct audpcm_buffer_node, list);
631 list_del(&buf_node->list);
632 payload.aio_buf = buf_node->buf;
633 audpcm_post_event(audio, AUDIO_EVENT_WRITE_DONE,
634 payload);
635 kfree(buf_node);
636 }
637 audio->drv_status &= ~ADRV_STATUS_OBUF_GIVEN;
638 audio->out_needed = 0;
639 atomic_set(&audio->out_bytes, 0);
640}
641
642static void audio_flush(struct audio *audio)
643{
Manish Dewangana4f1df02012-02-08 17:06:54 +0530644 unsigned long flags;
645
646 spin_lock_irqsave(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700647 audio->out[0].used = 0;
648 audio->out[1].used = 0;
649 audio->out_head = 0;
650 audio->out_tail = 0;
651 audio->reserved = 0;
652 audio->out_needed = 0;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530653 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700654 atomic_set(&audio->out_bytes, 0);
655}
656
657static void audio_ioport_reset(struct audio *audio)
658{
659 if (audio->drv_status & ADRV_STATUS_AIO_INTF) {
660 /* If fsync is in progress, make sure
661 * return value of fsync indicates
662 * abort due to flush
663 */
664 if (audio->drv_status & ADRV_STATUS_FSYNC) {
665 MM_DBG("fsync in progress\n");
666 wake_up(&audio->write_wait);
667 mutex_lock(&audio->write_lock);
668 audio->drv_ops.out_flush(audio);
669 mutex_unlock(&audio->write_lock);
670 } else
671 audio->drv_ops.out_flush(audio);
672 } else {
673 /* Make sure read/write thread are free from
674 * sleep and knowing that system is not able
675 * to process io request at the moment
676 */
677 wake_up(&audio->write_wait);
678 mutex_lock(&audio->write_lock);
679 audio->drv_ops.out_flush(audio);
680 mutex_unlock(&audio->write_lock);
681 }
682}
683
684static int audpcm_events_pending(struct audio *audio)
685{
686 unsigned long flags;
687 int empty;
688
689 spin_lock_irqsave(&audio->event_queue_lock, flags);
690 empty = !list_empty(&audio->event_queue);
691 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
692 return empty || audio->event_abort;
693}
694
695static void audpcm_reset_event_queue(struct audio *audio)
696{
697 unsigned long flags;
698 struct audpcm_event *drv_evt;
699 struct list_head *ptr, *next;
700
701 spin_lock_irqsave(&audio->event_queue_lock, flags);
702 list_for_each_safe(ptr, next, &audio->event_queue) {
703 drv_evt = list_first_entry(&audio->event_queue,
704 struct audpcm_event, list);
705 list_del(&drv_evt->list);
706 kfree(drv_evt);
707 }
708 list_for_each_safe(ptr, next, &audio->free_event_queue) {
709 drv_evt = list_first_entry(&audio->free_event_queue,
710 struct audpcm_event, list);
711 list_del(&drv_evt->list);
712 kfree(drv_evt);
713 }
714 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
715
716 return;
717}
718
719static long audpcm_process_event_req(struct audio *audio, void __user *arg)
720{
721 long rc;
722 struct msm_audio_event usr_evt;
723 struct audpcm_event *drv_evt = NULL;
724 int timeout;
725 unsigned long flags;
726
727 if (copy_from_user(&usr_evt, arg, sizeof(struct msm_audio_event)))
728 return -EFAULT;
729
730 timeout = (int) usr_evt.timeout_ms;
731
732 if (timeout > 0) {
733 rc = wait_event_interruptible_timeout(
734 audio->event_wait, audpcm_events_pending(audio),
735 msecs_to_jiffies(timeout));
736 if (rc == 0)
737 return -ETIMEDOUT;
738 } else {
739 rc = wait_event_interruptible(
740 audio->event_wait, audpcm_events_pending(audio));
741 }
742
743 if (rc < 0)
744 return rc;
745
746 if (audio->event_abort) {
747 audio->event_abort = 0;
748 return -ENODEV;
749 }
750
751 spin_lock_irqsave(&audio->event_queue_lock, flags);
752 if (!list_empty(&audio->event_queue)) {
753 drv_evt = list_first_entry(&audio->event_queue,
754 struct audpcm_event, list);
755 list_del(&drv_evt->list);
756 }
757 if (drv_evt) {
758 usr_evt.event_type = drv_evt->event_type;
759 usr_evt.event_payload = drv_evt->payload;
760 list_add_tail(&drv_evt->list, &audio->free_event_queue);
761 } else
762 rc = -1;
763 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
764
765 if (drv_evt && drv_evt->event_type == AUDIO_EVENT_WRITE_DONE) {
766 mutex_lock(&audio->lock);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530767 audpcm_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700768 drv_evt->payload.aio_buf.buf_len, 0);
769 mutex_unlock(&audio->lock);
770 }
771 if (!rc && copy_to_user(arg, &usr_evt, sizeof(usr_evt)))
772 rc = -EFAULT;
773
774 return rc;
775}
776
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530777static int audpcm_ion_check(struct audio *audio,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700778 void *vaddr, unsigned long len)
779{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530780 struct audpcm_ion_region *region_elt;
781 struct audpcm_ion_region t = {.vaddr = vaddr, .len = len };
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700782
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530783 list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784 if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
785 OVERLAPS(region_elt, &t)) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530786 MM_ERR("[%p]:region (vaddr %p len %ld)"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700787 " clashes with registered region"
788 " (vaddr %p paddr %p len %ld)\n",
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530789 audio, vaddr, len,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700790 region_elt->vaddr,
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530791 (void *)region_elt->paddr, region_elt->len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700792 return -EINVAL;
793 }
794 }
795
796 return 0;
797}
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530798static int audpcm_ion_add(struct audio *audio,
799 struct msm_audio_ion_info *info)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530801 ion_phys_addr_t paddr;
802 size_t len;
803 unsigned long kvaddr;
804 struct audpcm_ion_region *region;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805 int rc = -EINVAL;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530806 struct ion_handle *handle;
807 unsigned long ionflag;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530809 MM_ERR("\n"); /* Macro prints the file name and function */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700810 region = kmalloc(sizeof(*region), GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700811
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530812 if (!region) {
813 rc = -ENOMEM;
814 goto end;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700815 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530816 handle = ion_import_dma_buf(audio->client, info->fd);
817 if (IS_ERR_OR_NULL(handle)) {
818 pr_err("%s: could not get handle of the given fd\n", __func__);
819 goto import_error;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700820 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530821 rc = ion_handle_get_flags(audio->client, handle, &ionflag);
822 if (rc) {
823 pr_err("%s: could not get flags for the handle\n", __func__);
824 goto flag_error;
825 }
Mitchel Humpherys911b4b72012-09-12 14:42:50 -0700826 kvaddr = (unsigned long)ion_map_kernel(audio->client, handle);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530827 if (IS_ERR_OR_NULL((void *)kvaddr)) {
828 pr_err("%s: could not get virtual address\n", __func__);
829 goto map_error;
830 }
831 rc = ion_phys(audio->client, handle, &paddr, &len);
832 if (rc) {
833 pr_err("%s: could not get physical address\n", __func__);
834 goto ion_error;
835 }
836 rc = audpcm_ion_check(audio, info->vaddr, len);
837 if (rc < 0) {
838 MM_ERR("audpcm_ion_check failed\n");
839 goto ion_error;
840 }
841 region->handle = handle;
842 region->vaddr = info->vaddr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700843 region->fd = info->fd;
844 region->paddr = paddr;
845 region->kvaddr = kvaddr;
846 region->len = len;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700847 region->ref_cnt = 0;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530848 MM_DBG("[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
849 audio, region->paddr, region->vaddr,
850 region->len, region->kvaddr);
851 list_add_tail(&region->list, &audio->ion_region_queue);
852
853 return rc;
854
855ion_error:
856 ion_unmap_kernel(audio->client, handle);
857map_error:
858flag_error:
859 ion_free(audio->client, handle);
860import_error:
861 kfree(region);
862end:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700863 return rc;
864}
865
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530866static int audpcm_ion_remove(struct audio *audio,
867 struct msm_audio_ion_info *info)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700868{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530869 struct audpcm_ion_region *region;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700870 struct list_head *ptr, *next;
871 int rc = -EINVAL;
872
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530873 list_for_each_safe(ptr, next, &audio->ion_region_queue) {
874 region = list_entry(ptr, struct audpcm_ion_region, list);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700875
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530876 if (region != NULL && (region->fd == info->fd) &&
877 (region->vaddr == info->vaddr)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700878 if (region->ref_cnt) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530879 MM_DBG("%s[%p]:region %p in use ref_cnt %d\n",
880 __func__, audio, region,
881 region->ref_cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700882 break;
883 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530884 MM_DBG("remove region fd %d vaddr %p\n",
885 info->fd, info->vaddr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700886 list_del(&region->list);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530887 ion_unmap_kernel(audio->client, region->handle);
888 ion_free(audio->client, region->handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700889 kfree(region);
890 rc = 0;
891 break;
892 }
893 }
894
895 return rc;
896}
897
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530898static int audpcm_ion_lookup_vaddr(struct audio *audio, void *addr,
899 unsigned long len, struct audpcm_ion_region **region)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700900{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530901 struct audpcm_ion_region *region_elt;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700902 int match_count = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700903 *region = NULL;
904
905 /* returns physical address or zero */
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530906 list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700907 if (addr >= region_elt->vaddr &&
908 addr < region_elt->vaddr + region_elt->len &&
909 addr + len <= region_elt->vaddr + region_elt->len) {
910 /* offset since we could pass vaddr inside a registerd
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530911 * ion buffer
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700912 */
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530913
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700914 match_count++;
915 if (!*region)
916 *region = region_elt;
917 }
918 }
919
920 if (match_count > 1) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530921 MM_ERR("%s[%p]:multiple hits for vaddr %p, len %ld\n",
922 __func__, audio, addr, len);
923 list_for_each_entry(region_elt, &audio->ion_region_queue,
924 list) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700925 if (addr >= region_elt->vaddr &&
926 addr < region_elt->vaddr + region_elt->len &&
927 addr + len <= region_elt->vaddr + region_elt->len)
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530928 MM_ERR("\t%s[%p]:%p, %ld --> %p\n",
929 __func__, audio,
930 region_elt->vaddr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700931 region_elt->len,
932 (void *)region_elt->paddr);
933 }
934 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700935 return *region ? 0 : -1;
936}
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530937static unsigned long audpcm_ion_fixup(struct audio *audio, void *addr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700938 unsigned long len, int ref_up)
939{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530940 struct audpcm_ion_region *region;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700941 unsigned long paddr;
942 int ret;
943
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530944 ret = audpcm_ion_lookup_vaddr(audio, addr, len, &region);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700945 if (ret) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530946 MM_ERR("%s[%p]:lookup (%p, %ld) failed\n",
947 __func__, audio, addr, len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700948 return 0;
949 }
950 if (ref_up)
951 region->ref_cnt++;
952 else
953 region->ref_cnt--;
954 MM_DBG("found region %p ref_cnt %d\n", region, region->ref_cnt);
955 paddr = region->paddr + (addr - region->vaddr);
956 return paddr;
957}
958
959/* audio -> lock must be held at this point */
960static int audpcm_aio_buf_add(struct audio *audio, unsigned dir,
961 void __user *arg)
962{
963 unsigned long flags;
964 struct audpcm_buffer_node *buf_node;
965
966 buf_node = kmalloc(sizeof(*buf_node), GFP_KERNEL);
967
968 if (!buf_node)
969 return -ENOMEM;
970
971 if (copy_from_user(&buf_node->buf, arg, sizeof(buf_node->buf))) {
972 kfree(buf_node);
973 return -EFAULT;
974 }
975
976 MM_DBG("node %p dir %x buf_addr %p buf_len %d data_len %d\n",
977 buf_node, dir, buf_node->buf.buf_addr,
978 buf_node->buf.buf_len, buf_node->buf.data_len);
979
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530980 buf_node->paddr = audpcm_ion_fixup(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700981 audio, buf_node->buf.buf_addr,
982 buf_node->buf.buf_len, 1);
983 if (dir) {
984 /* write */
985 if (!buf_node->paddr ||
986 (buf_node->paddr & 0x1) ||
987 (buf_node->buf.data_len & 0x1) ||
988 (!buf_node->buf.data_len)) {
989 kfree(buf_node);
990 return -EINVAL;
991 }
992 spin_lock_irqsave(&audio->dsp_lock, flags);
993 list_add_tail(&buf_node->list, &audio->out_queue);
994 spin_unlock_irqrestore(&audio->dsp_lock, flags);
995 audio->drv_ops.send_data(audio, 0);
996 }
997
998 MM_DBG("Add buf_node %p paddr %lx\n", buf_node, buf_node->paddr);
999
1000 return 0;
1001}
1002
1003static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1004{
1005 struct audio *audio = file->private_data;
1006 int rc = 0;
1007
1008 MM_DBG("cmd = %d\n", cmd);
1009
1010 if (cmd == AUDIO_GET_STATS) {
1011 struct msm_audio_stats stats;
1012 stats.byte_count = audpp_avsync_byte_count(audio->dec_id);
1013 stats.sample_count = audpp_avsync_sample_count(audio->dec_id);
1014 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
1015 return -EFAULT;
1016 return 0;
1017 }
1018 if (cmd == AUDIO_SET_VOLUME) {
1019 unsigned long flags;
1020 spin_lock_irqsave(&audio->dsp_lock, flags);
1021 audio->volume = arg;
1022 if (audio->running)
1023 audpp_set_volume_and_pan(audio->dec_id, arg, 0);
1024 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1025 return 0;
1026 }
1027 if (cmd == AUDIO_GET_EVENT) {
1028 MM_DBG("AUDIO_GET_EVENT\n");
1029 if (mutex_trylock(&audio->get_event_lock)) {
1030 rc = audpcm_process_event_req(audio,
1031 (void __user *) arg);
1032 mutex_unlock(&audio->get_event_lock);
1033 } else
1034 rc = -EBUSY;
1035 return rc;
1036 }
1037
1038 if (cmd == AUDIO_ABORT_GET_EVENT) {
1039 audio->event_abort = 1;
1040 wake_up(&audio->event_wait);
1041 return 0;
1042 }
1043
1044 mutex_lock(&audio->lock);
1045 switch (cmd) {
1046 case AUDIO_START:
1047 MM_DBG("AUDIO_START\n");
1048 rc = audio_enable(audio);
1049 if (!rc) {
1050 rc = wait_event_interruptible_timeout(audio->wait,
1051 audio->dec_state != MSM_AUD_DECODER_STATE_NONE,
1052 msecs_to_jiffies(MSM_AUD_DECODER_WAIT_MS));
1053 MM_INFO("dec_state %d rc = %d\n", audio->dec_state, rc);
1054
1055 if (audio->dec_state != MSM_AUD_DECODER_STATE_SUCCESS)
1056 rc = -ENODEV;
1057 else
1058 rc = 0;
1059 }
1060 break;
1061 case AUDIO_STOP:
1062 MM_DBG("AUDIO_STOP\n");
1063 rc = audio_disable(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001064 audio_ioport_reset(audio);
1065 audio->stopped = 0;
1066 break;
1067 case AUDIO_FLUSH:
1068 MM_DBG("AUDIO_FLUSH\n");
1069 audio->wflush = 1;
1070 audio_ioport_reset(audio);
1071 if (audio->running) {
1072 audpp_flush(audio->dec_id);
1073 rc = wait_event_interruptible(audio->write_wait,
1074 !audio->wflush);
1075 if (rc < 0) {
1076 MM_ERR("AUDIO_FLUSH interrupted\n");
1077 rc = -EINTR;
1078 }
1079 } else {
1080 audio->wflush = 0;
1081 }
1082 break;
1083
1084 case AUDIO_SET_CONFIG: {
1085 struct msm_audio_config config;
1086 if (copy_from_user(&config, (void *) arg, sizeof(config))) {
1087 rc = -EFAULT;
1088 break;
1089 }
1090 if (config.channel_count == 1) {
1091 config.channel_count = AUDPP_CMD_PCM_INTF_MONO_V;
1092 } else if (config.channel_count == 2) {
1093 config.channel_count = AUDPP_CMD_PCM_INTF_STEREO_V;
1094 } else {
1095 rc = -EINVAL;
1096 break;
1097 }
1098 if (config.bits == 8)
1099 config.bits = AUDPP_CMD_WAV_PCM_WIDTH_8;
1100 else if (config.bits == 16)
1101 config.bits = AUDPP_CMD_WAV_PCM_WIDTH_16;
1102 else if (config.bits == 24)
1103 config.bits = AUDPP_CMD_WAV_PCM_WIDTH_24;
1104 else {
1105 rc = -EINVAL;
1106 break;
1107 }
1108 audio->out_sample_rate = config.sample_rate;
1109 audio->out_channel_mode = config.channel_count;
1110 audio->out_bits = config.bits;
1111 break;
1112 }
1113 case AUDIO_GET_CONFIG: {
1114 struct msm_audio_config config;
1115 config.buffer_size = (audio->out_dma_sz >> 1);
1116 config.buffer_count = 2;
1117 config.sample_rate = audio->out_sample_rate;
1118 if (audio->out_channel_mode == AUDPP_CMD_PCM_INTF_MONO_V)
1119 config.channel_count = 1;
1120 else
1121 config.channel_count = 2;
1122 if (audio->out_bits == AUDPP_CMD_WAV_PCM_WIDTH_8)
1123 config.bits = 8;
1124 else if (audio->out_bits == AUDPP_CMD_WAV_PCM_WIDTH_24)
1125 config.bits = 24;
1126 else
1127 config.bits = 16;
1128 config.unused[0] = 0;
1129 config.unused[1] = 0;
1130
1131 if (copy_to_user((void *) arg, &config, sizeof(config)))
1132 rc = -EFAULT;
1133 else
1134 rc = 0;
1135 break;
1136 }
1137
Santosh Mardi0be3b8e2011-07-06 10:00:21 +05301138
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001139 case AUDIO_PAUSE:
1140 MM_DBG("AUDIO_PAUSE %ld\n", arg);
1141 rc = audpp_pause(audio->dec_id, (int) arg);
1142 break;
1143
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301144 case AUDIO_REGISTER_ION: {
1145 struct msm_audio_ion_info info;
1146 MM_ERR("AUDIO_REGISTER_ION\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001147 if (copy_from_user(&info, (void *) arg, sizeof(info)))
1148 rc = -EFAULT;
1149 else
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301150 rc = audpcm_ion_add(audio, &info);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001151 break;
1152 }
1153
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301154 case AUDIO_DEREGISTER_ION: {
1155 struct msm_audio_ion_info info;
1156 MM_ERR("AUDIO_DEREGISTER_ION\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001157 if (copy_from_user(&info, (void *) arg, sizeof(info)))
1158 rc = -EFAULT;
1159 else
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301160 rc = audpcm_ion_remove(audio, &info);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001161 break;
1162 }
1163
1164 case AUDIO_ASYNC_WRITE:
1165 if (audio->drv_status & ADRV_STATUS_FSYNC)
1166 rc = -EBUSY;
1167 else
1168 rc = audpcm_aio_buf_add(audio, 1, (void __user *) arg);
1169 break;
1170
1171 case AUDIO_ASYNC_READ:
1172 MM_ERR("AUDIO_ASYNC_READ not supported\n");
1173 rc = -EPERM;
1174 break;
1175
1176 default:
1177 rc = -EINVAL;
1178 }
1179 mutex_unlock(&audio->lock);
1180 return rc;
1181}
1182
1183/* Only useful in tunnel-mode */
1184int audpcm_async_fsync(struct audio *audio)
1185{
1186 int rc = 0;
1187
1188 MM_DBG("\n"); /* Macro prints the file name and function */
1189
1190 /* Blocking client sends more data */
1191 mutex_lock(&audio->lock);
1192 audio->drv_status |= ADRV_STATUS_FSYNC;
1193 mutex_unlock(&audio->lock);
1194
1195 mutex_lock(&audio->write_lock);
1196 /* pcm dmamiss message is sent continously
1197 * when decoder is starved so no race
1198 * condition concern
1199 */
1200 audio->teos = 0;
1201
1202 rc = wait_event_interruptible(audio->write_wait,
1203 (audio->teos && audio->out_needed &&
1204 list_empty(&audio->out_queue))
1205 || audio->wflush || audio->stopped);
1206
1207 if (audio->stopped || audio->wflush)
1208 rc = -EBUSY;
1209
1210 mutex_unlock(&audio->write_lock);
1211 mutex_lock(&audio->lock);
1212 audio->drv_status &= ~ADRV_STATUS_FSYNC;
1213 mutex_unlock(&audio->lock);
1214
1215 return rc;
1216}
1217
1218int audpcm_sync_fsync(struct audio *audio)
1219{
1220 struct buffer *frame;
1221 int rc = 0;
1222
1223 MM_DBG("\n"); /* Macro prints the file name and function */
1224
1225 mutex_lock(&audio->write_lock);
1226
1227 rc = wait_event_interruptible(audio->write_wait,
1228 (!audio->out[0].used &&
1229 !audio->out[1].used &&
1230 audio->out_needed) || audio->wflush);
1231
1232 if (rc < 0)
1233 goto done;
1234 else if (audio->wflush) {
1235 rc = -EBUSY;
1236 goto done;
1237 }
1238
1239 if (audio->reserved) {
1240 MM_DBG("send reserved byte\n");
1241 frame = audio->out + audio->out_tail;
1242 ((char *) frame->data)[0] = audio->rsv_byte;
1243 ((char *) frame->data)[1] = 0;
1244 frame->used = 2;
1245 audio->drv_ops.send_data(audio, 0);
1246
1247 rc = wait_event_interruptible(audio->write_wait,
1248 (!audio->out[0].used &&
1249 !audio->out[1].used &&
1250 audio->out_needed) || audio->wflush);
1251
1252 if (rc < 0)
1253 goto done;
1254 else if (audio->wflush) {
1255 rc = -EBUSY;
1256 goto done;
1257 }
1258 }
1259
1260 /* pcm dmamiss message is sent continously
1261 * when decoder is starved so no race
1262 * condition concern
1263 */
1264 audio->teos = 0;
1265
1266 rc = wait_event_interruptible(audio->write_wait,
1267 audio->teos || audio->wflush);
1268
1269 if (audio->wflush)
1270 rc = -EBUSY;
1271
1272done:
1273 mutex_unlock(&audio->write_lock);
1274 return rc;
1275}
1276
Steve Mucklef132c6c2012-06-06 18:30:57 -07001277int audpcm_fsync(struct file *file, loff_t a, loff_t b, int datasync)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001278{
1279 struct audio *audio = file->private_data;
1280
1281 if (!audio->running)
1282 return -EINVAL;
1283
1284 return audio->drv_ops.fsync(audio);
1285}
1286
1287static ssize_t audio_write(struct file *file, const char __user *buf,
1288 size_t count, loff_t *pos)
1289{
1290 struct audio *audio = file->private_data;
1291 const char __user *start = buf;
1292 struct buffer *frame;
1293 size_t xfer;
1294 char *cpy_ptr;
1295 int rc = 0;
1296 unsigned dsize;
1297
1298 if (audio->drv_status & ADRV_STATUS_AIO_INTF)
1299 return -EPERM;
1300
1301 MM_DBG("cnt=%d\n", count);
1302
1303 mutex_lock(&audio->write_lock);
1304 while (count > 0) {
1305 frame = audio->out + audio->out_head;
1306 cpy_ptr = frame->data;
1307 dsize = 0;
1308 rc = wait_event_interruptible(audio->write_wait,
1309 (frame->used == 0)
1310 || (audio->stopped)
1311 || (audio->wflush));
1312 if (rc < 0)
1313 break;
1314 if (audio->stopped || audio->wflush) {
1315 rc = -EBUSY;
1316 break;
1317 }
1318
1319 if (audio->reserved) {
1320 MM_DBG("append reserved byte %x\n", audio->rsv_byte);
1321 *cpy_ptr = audio->rsv_byte;
1322 xfer = (count > (frame->size - 1)) ?
1323 frame->size - 1 : count;
1324 cpy_ptr++;
1325 dsize = 1;
1326 audio->reserved = 0;
1327 } else
1328 xfer = (count > frame->size) ? frame->size : count;
1329
1330 if (copy_from_user(cpy_ptr, buf, xfer)) {
1331 rc = -EFAULT;
1332 break;
1333 }
1334
1335 dsize += xfer;
1336 if (dsize & 1) {
1337 audio->rsv_byte = ((char *) frame->data)[dsize - 1];
1338 MM_DBG("odd length buf reserve last byte %x\n",
1339 audio->rsv_byte);
1340 audio->reserved = 1;
1341 dsize--;
1342 }
1343 count -= xfer;
1344 buf += xfer;
1345
1346 if (dsize > 0) {
1347 audio->out_head ^= 1;
1348 frame->used = dsize;
1349 audio->drv_ops.send_data(audio, 0);
1350 }
1351 }
1352 mutex_unlock(&audio->write_lock);
1353 if (buf > start)
1354 return buf - start;
1355
1356 return rc;
1357}
1358
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301359static void audpcm_reset_ion_region(struct audio *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001360{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301361 struct audpcm_ion_region *region;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001362 struct list_head *ptr, *next;
1363
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301364 list_for_each_safe(ptr, next, &audio->ion_region_queue) {
1365 region = list_entry(ptr, struct audpcm_ion_region, list);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001366 list_del(&region->list);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301367 ion_unmap_kernel(audio->client, region->handle);
1368 ion_free(audio->client, region->handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001369 kfree(region);
1370 }
1371
1372 return;
1373}
1374
1375static int audio_release(struct inode *inode, struct file *file)
1376{
1377 struct audio *audio = file->private_data;
1378
1379 MM_DBG("audio instance 0x%08x freeing\n", (int)audio);
1380 mutex_lock(&audio->lock);
1381 audio_disable(audio);
1382 if (audio->rmt_resource_released == 0)
1383 rmt_put_resource(audio);
1384 audio->drv_ops.out_flush(audio);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301385 audpcm_reset_ion_region(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001386
1387 msm_adsp_put(audio->audplay);
1388 audpp_adec_free(audio->dec_id);
1389#ifdef CONFIG_HAS_EARLYSUSPEND
1390 unregister_early_suspend(&audio->suspend_ctl.node);
1391#endif
1392 audio->opened = 0;
1393 audio->event_abort = 1;
1394 wake_up(&audio->event_wait);
1395 audpcm_reset_event_queue(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001396 mutex_unlock(&audio->lock);
1397#ifdef CONFIG_DEBUG_FS
1398 if (audio->dentry)
1399 debugfs_remove(audio->dentry);
1400#endif
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301401 ion_client_destroy(audio->client);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001402 kfree(audio);
1403 return 0;
1404}
1405
1406static void audpcm_post_event(struct audio *audio, int type,
1407 union msm_audio_event_payload payload)
1408{
1409 struct audpcm_event *e_node = NULL;
1410 unsigned long flags;
1411
1412 spin_lock_irqsave(&audio->event_queue_lock, flags);
1413
1414 if (!list_empty(&audio->free_event_queue)) {
1415 e_node = list_first_entry(&audio->free_event_queue,
1416 struct audpcm_event, list);
1417 list_del(&e_node->list);
1418 } else {
1419 e_node = kmalloc(sizeof(struct audpcm_event), GFP_ATOMIC);
1420 if (!e_node) {
1421 MM_ERR("No mem to post event %d\n", type);
1422 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
1423 return;
1424 }
1425 }
1426
1427 e_node->event_type = type;
1428 e_node->payload = payload;
1429
1430 list_add_tail(&e_node->list, &audio->event_queue);
1431 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
1432 wake_up(&audio->event_wait);
1433}
1434
1435#ifdef CONFIG_HAS_EARLYSUSPEND
1436static void audpcm_suspend(struct early_suspend *h)
1437{
1438 struct audpcm_suspend_ctl *ctl =
1439 container_of(h, struct audpcm_suspend_ctl, node);
1440 union msm_audio_event_payload payload;
1441
1442 MM_DBG("\n"); /* Macro prints the file name and function */
1443 audpcm_post_event(ctl->audio, AUDIO_EVENT_SUSPEND, payload);
1444}
1445
1446static void audpcm_resume(struct early_suspend *h)
1447{
1448 struct audpcm_suspend_ctl *ctl =
1449 container_of(h, struct audpcm_suspend_ctl, node);
1450 union msm_audio_event_payload payload;
1451
1452 MM_DBG("\n"); /* Macro prints the file name and function */
1453 audpcm_post_event(ctl->audio, AUDIO_EVENT_RESUME, payload);
1454}
1455#endif
1456
1457#ifdef CONFIG_DEBUG_FS
1458static ssize_t audpcm_debug_open(struct inode *inode, struct file *file)
1459{
1460 file->private_data = inode->i_private;
1461 return 0;
1462}
1463
1464static ssize_t audpcm_debug_read(struct file *file, char __user *buf,
1465 size_t count, loff_t *ppos)
1466{
1467 const int debug_bufmax = 4096;
1468 static char buffer[4096];
1469 int n = 0;
1470 struct audio *audio = file->private_data;
1471
1472 mutex_lock(&audio->lock);
1473 n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
1474 n += scnprintf(buffer + n, debug_bufmax - n,
1475 "enabled %d\n", audio->enabled);
1476 n += scnprintf(buffer + n, debug_bufmax - n,
1477 "stopped %d\n", audio->stopped);
1478 n += scnprintf(buffer + n, debug_bufmax - n,
1479 "out_buf_sz %d\n", audio->out[0].size);
1480 n += scnprintf(buffer + n, debug_bufmax - n,
1481 "volume %x \n", audio->volume);
1482 n += scnprintf(buffer + n, debug_bufmax - n,
1483 "sample rate %d \n", audio->out_sample_rate);
1484 n += scnprintf(buffer + n, debug_bufmax - n,
1485 "channel mode %d \n", audio->out_channel_mode);
1486 mutex_unlock(&audio->lock);
1487 /* Following variables are only useful for debugging when
1488 * when playback halts unexpectedly. Thus, no mutual exclusion
1489 * enforced
1490 */
1491 n += scnprintf(buffer + n, debug_bufmax - n,
1492 "wflush %d\n", audio->wflush);
1493 n += scnprintf(buffer + n, debug_bufmax - n,
1494 "running %d \n", audio->running);
1495 n += scnprintf(buffer + n, debug_bufmax - n,
1496 "dec state %d \n", audio->dec_state);
1497 n += scnprintf(buffer + n, debug_bufmax - n,
1498 "out_needed %d \n", audio->out_needed);
1499 n += scnprintf(buffer + n, debug_bufmax - n,
1500 "out_head %d \n", audio->out_head);
1501 n += scnprintf(buffer + n, debug_bufmax - n,
1502 "out_tail %d \n", audio->out_tail);
1503 n += scnprintf(buffer + n, debug_bufmax - n,
1504 "out[0].used %d \n", audio->out[0].used);
1505 n += scnprintf(buffer + n, debug_bufmax - n,
1506 "out[1].used %d \n", audio->out[1].used);
1507 buffer[n] = 0;
1508 return simple_read_from_buffer(buf, count, ppos, buffer, n);
1509}
1510
1511static const struct file_operations audpcm_debug_fops = {
1512 .read = audpcm_debug_read,
1513 .open = audpcm_debug_open,
1514};
1515#endif
1516
1517static int audio_open(struct inode *inode, struct file *file)
1518{
1519 struct audio *audio = NULL;
1520 int rc, i, dec_attrb, decid;
1521 struct audpcm_event *e_node = NULL;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301522 unsigned mem_sz = DMASZ_MAX;
1523 unsigned long ionflag = 0;
1524 ion_phys_addr_t addr = 0;
1525 struct ion_handle *handle = NULL;
1526 struct ion_client *client = NULL;
1527 int len = 0;
1528
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001529
1530#ifdef CONFIG_DEBUG_FS
1531 /* 4 bytes represents decoder number, 1 byte for terminate string */
1532 char name[sizeof "msm_pcm_dec_" + 5];
1533#endif
1534
1535 /* Allocate audio instance, set to zero */
1536 audio = kzalloc(sizeof(struct audio), GFP_KERNEL);
1537 if (!audio) {
1538 MM_ERR("no memory to allocate audio instance \n");
1539 rc = -ENOMEM;
1540 goto done;
1541 }
1542 MM_DBG("audio instance 0x%08x created\n", (int)audio);
1543
1544 /* Allocate the decoder */
1545 dec_attrb = AUDDEC_DEC_PCM;
1546 if (file->f_mode & FMODE_READ) {
1547 MM_ERR("Non-Tunneled mode not supported\n");
1548 rc = -EPERM;
1549 kfree(audio);
1550 goto done;
1551 } else
1552 dec_attrb |= MSM_AUD_MODE_TUNNEL;
1553
1554 decid = audpp_adec_alloc(dec_attrb, &audio->module_name,
1555 &audio->queue_id);
1556 if (decid < 0) {
1557 MM_ERR("No free decoder available\n");
1558 rc = -ENODEV;
1559 MM_DBG("audio instance 0x%08x freeing\n", (int)audio);
1560 kfree(audio);
1561 goto done;
1562 }
1563 audio->dec_id = decid & MSM_AUD_DECODER_MASK;
1564
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301565 client = msm_ion_client_create(UINT_MAX, "Audio_PCM_Client");
1566 if (IS_ERR_OR_NULL(client)) {
1567 pr_err("Unable to create ION client\n");
1568 rc = -ENOMEM;
1569 goto client_create_error;
1570 }
1571 audio->client = client;
1572
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001573 /* Non AIO interface */
1574 if (!(file->f_flags & O_NONBLOCK)) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301575
1576 MM_DBG("memsz = %d\n", mem_sz);
1577
1578 handle = ion_alloc(client, mem_sz, SZ_4K,
Hanumant Singh7d72bad2012-08-29 18:39:44 -07001579 ION_HEAP(ION_AUDIO_HEAP_ID), 0);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301580 if (IS_ERR_OR_NULL(handle)) {
1581 MM_ERR("Unable to create allocate O/P buffers\n");
1582 rc = -ENOMEM;
1583 goto output_buff_alloc_error;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001584 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301585 audio->output_buff_handle = handle;
1586
1587 rc = ion_phys(client , handle, &addr, &len);
1588 if (rc) {
1589 MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
1590 (unsigned int) addr, (unsigned int) len);
1591 goto output_buff_get_phys_error;
1592 } else {
1593 MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
1594 (unsigned int) addr, (unsigned int) len);
1595 }
1596 audio->phys = (int32_t)addr;
1597
1598
1599 rc = ion_handle_get_flags(client, handle, &ionflag);
1600 if (rc) {
1601 MM_ERR("could not get flags for the handle\n");
1602 goto output_buff_get_flags_error;
1603 }
1604
Mitchel Humpherys911b4b72012-09-12 14:42:50 -07001605 audio->map_v_write = ion_map_kernel(client, handle);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301606 if (IS_ERR(audio->map_v_write)) {
1607 MM_ERR("could not map write buffers\n");
1608 rc = -ENOMEM;
1609 goto output_buff_map_error;
1610 }
1611 audio->data = audio->map_v_write;
1612 MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
1613 audio->phys, (int)audio->data);
1614
1615 audio->out_dma_sz = mem_sz;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001616 }
1617
1618 rc = audmgr_open(&audio->audmgr);
1619 if (rc)
1620 goto err;
1621
1622 rc = msm_adsp_get(audio->module_name, &audio->audplay,
1623 &audpcmdec_adsp_ops, audio);
1624 if (rc) {
1625 MM_ERR("failed to get %s module\n", audio->module_name);
1626 audmgr_close(&audio->audmgr);
1627 goto err;
1628 }
1629
1630 rc = rmt_get_resource(audio);
1631 if (rc) {
1632 MM_ERR("ADSP resources are not available for PCM session \
1633 0x%08x on decoder: %d\n", (int)audio, audio->dec_id);
1634 audmgr_close(&audio->audmgr);
1635 msm_adsp_put(audio->audplay);
1636 goto err;
1637 }
1638
1639 if (file->f_flags & O_NONBLOCK) {
1640 MM_DBG("set to aio interface\n");
1641 audio->drv_status |= ADRV_STATUS_AIO_INTF;
1642 audio->drv_ops.send_data = audpcm_async_send_data;
1643 audio->drv_ops.out_flush = audpcm_async_flush;
1644 audio->drv_ops.fsync = audpcm_async_fsync;
1645 } else {
1646 MM_DBG("set to std io interface\n");
1647 audio->drv_ops.send_data = audplay_send_data;
1648 audio->drv_ops.out_flush = audio_flush;
1649 audio->drv_ops.fsync = audpcm_sync_fsync;
1650 audio->out[0].data = audio->data + 0;
1651 audio->out[0].addr = audio->phys + 0;
1652 audio->out[0].size = (audio->out_dma_sz >> 1);
1653
1654 audio->out[1].data = audio->data + audio->out[0].size;
1655 audio->out[1].addr = audio->phys + audio->out[0].size;
1656 audio->out[1].size = audio->out[0].size;
1657 }
1658
1659 /* Initialize all locks of audio instance */
1660 mutex_init(&audio->lock);
1661 mutex_init(&audio->write_lock);
1662 mutex_init(&audio->get_event_lock);
1663 spin_lock_init(&audio->dsp_lock);
1664 init_waitqueue_head(&audio->write_wait);
1665 INIT_LIST_HEAD(&audio->out_queue);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301666 INIT_LIST_HEAD(&audio->ion_region_queue);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001667 INIT_LIST_HEAD(&audio->free_event_queue);
1668 INIT_LIST_HEAD(&audio->event_queue);
1669 init_waitqueue_head(&audio->wait);
1670 init_waitqueue_head(&audio->event_wait);
1671 spin_lock_init(&audio->event_queue_lock);
1672
1673 audio->out_sample_rate = 44100;
1674 audio->out_channel_mode = AUDPP_CMD_PCM_INTF_STEREO_V;
1675 audio->out_bits = AUDPP_CMD_WAV_PCM_WIDTH_16;
1676 audio->volume = 0x2000;
1677 audio->drv_ops.out_flush(audio);
1678
1679 file->private_data = audio;
1680 audio->opened = 1;
1681
1682#ifdef CONFIG_DEBUG_FS
1683 snprintf(name, sizeof name, "msm_pcm_dec_%04x", audio->dec_id);
1684 audio->dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
1685 NULL, (void *) audio, &audpcm_debug_fops);
1686
1687 if (IS_ERR(audio->dentry))
1688 MM_DBG("debugfs_create_file failed\n");
1689#endif
1690#ifdef CONFIG_HAS_EARLYSUSPEND
1691 audio->suspend_ctl.node.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
1692 audio->suspend_ctl.node.resume = audpcm_resume;
1693 audio->suspend_ctl.node.suspend = audpcm_suspend;
1694 audio->suspend_ctl.audio = audio;
1695 register_early_suspend(&audio->suspend_ctl.node);
1696#endif
1697 for (i = 0; i < AUDPCM_EVENT_NUM; i++) {
1698 e_node = kmalloc(sizeof(struct audpcm_event), GFP_KERNEL);
1699 if (e_node)
1700 list_add_tail(&e_node->list, &audio->free_event_queue);
1701 else {
1702 MM_ERR("event pkt alloc failed\n");
1703 break;
1704 }
1705 }
1706done:
1707 return rc;
1708err:
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301709 ion_unmap_kernel(client, audio->output_buff_handle);
1710output_buff_map_error:
1711output_buff_get_flags_error:
1712output_buff_get_phys_error:
1713 ion_free(client, audio->output_buff_handle);
1714output_buff_alloc_error:
1715 ion_client_destroy(client);
1716client_create_error:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001717 audpp_adec_free(audio->dec_id);
1718 MM_DBG("audio instance 0x%08x freeing\n", (int)audio);
1719 kfree(audio);
1720 return rc;
1721}
1722
1723static const struct file_operations audio_pcm_fops = {
1724 .owner = THIS_MODULE,
1725 .open = audio_open,
1726 .release = audio_release,
1727 .write = audio_write,
1728 .unlocked_ioctl = audio_ioctl,
1729 .fsync = audpcm_fsync,
1730};
1731
1732struct miscdevice audio_pcm_misc = {
1733 .minor = MISC_DYNAMIC_MINOR,
1734 .name = "msm_pcm_dec",
1735 .fops = &audio_pcm_fops,
1736};
1737
1738static int __init audio_init(void)
1739{
1740 return misc_register(&audio_pcm_misc);
1741}
1742
1743device_initcall(audio_init);