blob: a606bd5b336c12efa76d091a9f3511f934cd5752 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/qdsp5/audio_mp3.c
2 *
3 * mp3 audio output device
4 *
5 * Copyright (C) 2008 Google, Inc.
6 * Copyright (C) 2008 HTC Corporation
Manish Dewangana4f1df02012-02-08 17:06:54 +05307 * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07008 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053020#include <asm/atomic.h>
21#include <asm/ioctls.h>
22
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070023#include <linux/module.h>
24#include <linux/fs.h>
25#include <linux/miscdevice.h>
26#include <linux/uaccess.h>
27#include <linux/kthread.h>
28#include <linux/wait.h>
29#include <linux/dma-mapping.h>
30#include <linux/debugfs.h>
31#include <linux/delay.h>
32#include <linux/earlysuspend.h>
33#include <linux/list.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070034#include <linux/slab.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070035#include <linux/msm_audio.h>
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053036#include <linux/memory_alloc.h>
Mitchel Humpherys1da6ebe2012-09-06 10:15:56 -070037#include <linux/msm_ion.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070038
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053039#include <mach/msm_adsp.h>
40#include <mach/iommu.h>
41#include <mach/iommu_domains.h>
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053042#include <mach/msm_memtypes.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043#include <mach/qdsp5/qdsp5audppcmdi.h>
44#include <mach/qdsp5/qdsp5audppmsg.h>
Manish Dewanganfa8a6b62012-07-09 16:23:27 +053045#include <mach/qdsp5/qdsp5audpp.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046#include <mach/qdsp5/qdsp5audplaycmdi.h>
47#include <mach/qdsp5/qdsp5audplaymsg.h>
48#include <mach/qdsp5/qdsp5rmtcmdi.h>
49#include <mach/debug_mm.h>
50
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053051#include "audmgr.h"
52
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070053#define ADRV_STATUS_AIO_INTF 0x00000001
54#define ADRV_STATUS_OBUF_GIVEN 0x00000002
55#define ADRV_STATUS_IBUF_GIVEN 0x00000004
56#define ADRV_STATUS_FSYNC 0x00000008
57
58/* Size must be power of 2 */
59#define BUFSZ_MAX 32768
60#define BUFSZ_MIN 4096
61#define DMASZ_MAX (BUFSZ_MAX * 2)
62#define DMASZ_MIN (BUFSZ_MIN * 2)
63
64#define AUDPLAY_INVALID_READ_PTR_OFFSET 0xFFFF
65#define AUDDEC_DEC_MP3 2
66
67#define PCM_BUFSZ_MIN 4800 /* Hold one stereo MP3 frame */
68#define PCM_BUF_MAX_COUNT 5 /* DSP only accepts 5 buffers at most
69 but support 2 buffers currently */
70#define ROUTING_MODE_FTRT 1
71#define ROUTING_MODE_RT 2
72/* Decoder status received from AUDPPTASK */
73#define AUDPP_DEC_STATUS_SLEEP 0
74#define AUDPP_DEC_STATUS_INIT 1
75#define AUDPP_DEC_STATUS_CFG 2
76#define AUDPP_DEC_STATUS_PLAY 3
77
78#define AUDMP3_METAFIELD_MASK 0xFFFF0000
79#define AUDMP3_EOS_FLG_OFFSET 0x0A /* Offset from beginning of buffer */
80#define AUDMP3_EOS_FLG_MASK 0x01
81#define AUDMP3_EOS_NONE 0x0 /* No EOS detected */
82#define AUDMP3_EOS_SET 0x1 /* EOS set in meta field */
83
84#define AUDMP3_EVENT_NUM 10 /* Default number of pre-allocated event packets */
85
86#define __CONTAINS(r, v, l) ({ \
87 typeof(r) __r = r; \
88 typeof(v) __v = v; \
89 typeof(v) __e = __v + l; \
90 int res = ((__v >= __r->vaddr) && \
91 (__e <= __r->vaddr + __r->len)); \
92 res; \
93})
94
95#define CONTAINS(r1, r2) ({ \
96 typeof(r2) __r2 = r2; \
97 __CONTAINS(r1, __r2->vaddr, __r2->len); \
98})
99
100#define IN_RANGE(r, v) ({ \
101 typeof(r) __r = r; \
102 typeof(v) __vv = v; \
103 int res = ((__vv >= __r->vaddr) && \
104 (__vv < (__r->vaddr + __r->len))); \
105 res; \
106})
107
108#define OVERLAPS(r1, r2) ({ \
109 typeof(r1) __r1 = r1; \
110 typeof(r2) __r2 = r2; \
111 typeof(__r2->vaddr) __v = __r2->vaddr; \
112 typeof(__v) __e = __v + __r2->len - 1; \
113 int res = (IN_RANGE(__r1, __v) || IN_RANGE(__r1, __e)); \
114 res; \
115})
116
117struct audio;
118
119struct buffer {
120 void *data;
121 unsigned size;
122 unsigned used; /* Input usage actual DSP produced PCM size */
123 unsigned addr;
124 unsigned short mfield_sz; /*only useful for data has meta field */
125};
126
127#ifdef CONFIG_HAS_EARLYSUSPEND
128struct audmp3_suspend_ctl {
129 struct early_suspend node;
130 struct audio *audio;
131};
132#endif
133
134struct audmp3_event {
135 struct list_head list;
136 int event_type;
137 union msm_audio_event_payload payload;
138};
139
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530140struct audmp3_ion_region {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141 struct list_head list;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530142 struct ion_handle *handle;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700143 int fd;
144 void *vaddr;
145 unsigned long paddr;
146 unsigned long kvaddr;
147 unsigned long len;
148 unsigned ref_cnt;
149};
150
151struct audmp3_buffer_node {
152 struct list_head list;
153 struct msm_audio_aio_buf buf;
154 unsigned long paddr;
155};
156
157struct audmp3_drv_operations {
158 void (*pcm_buf_update)(struct audio *, uint32_t *);
159 void (*buffer_refresh)(struct audio *);
160 void (*send_data)(struct audio *, unsigned);
161 void (*out_flush)(struct audio *);
162 void (*in_flush)(struct audio *);
163 int (*fsync)(struct audio *);
164};
165
166struct audio {
167 struct buffer out[2];
168
169 spinlock_t dsp_lock;
170
171 uint8_t out_head;
172 uint8_t out_tail;
173 uint8_t out_needed; /* number of buffers the dsp is waiting for */
174 unsigned out_dma_sz;
175 struct list_head out_queue; /* queue to retain output buffers */
176 atomic_t out_bytes;
177
178 struct mutex lock;
179 struct mutex write_lock;
180 wait_queue_head_t write_wait;
181
182 /* Host PCM section */
183 struct buffer in[PCM_BUF_MAX_COUNT];
184 struct mutex read_lock;
185 wait_queue_head_t read_wait; /* Wait queue for read */
186 char *read_data; /* pointer to reader buffer */
187 int32_t read_phys; /* physical address of reader buffer */
188 uint8_t read_next; /* index to input buffers to be read next */
189 uint8_t fill_next; /* index to buffer that DSP should be filling */
190 uint8_t pcm_buf_count; /* number of pcm buffer allocated */
191 struct list_head in_queue; /* queue to retain input buffers */
192 /* ---- End of Host PCM section */
193
194 struct msm_adsp_module *audplay;
195
196 /* configuration to use on next enable */
197 uint32_t out_sample_rate;
198 uint32_t out_channel_mode;
199
200 struct audmgr audmgr;
201
202 /* data allocated for various buffers */
203 char *data;
204 int32_t phys; /* physical address of write buffer */
Laura Abbott35111d32012-04-27 18:41:48 -0700205 void *map_v_read;
206 void *map_v_write;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207
208 uint32_t drv_status;
209 int mfield; /* meta field embedded in data */
210 int rflush; /* Read flush */
211 int wflush; /* Write flush */
212 int opened;
213 int enabled;
214 int running;
215 int stopped; /* set when stopped, cleared on flush */
216 int pcm_feedback;
217 int buf_refresh;
218 int rmt_resource_released;
219 int teos; /* valid only if tunnel mode & no data left for decoder */
220 enum msm_aud_decoder_state dec_state; /* Represents decoder state */
221 int reserved; /* A byte is being reserved */
222 char rsv_byte; /* Handle odd length user data */
223
224 const char *module_name;
225 unsigned queue_id;
226 uint16_t dec_id;
227 uint32_t read_ptr_offset;
228
229#ifdef CONFIG_HAS_EARLYSUSPEND
230 struct audmp3_suspend_ctl suspend_ctl;
231#endif
232
233#ifdef CONFIG_DEBUG_FS
234 struct dentry *dentry;
235#endif
236
237 wait_queue_head_t wait;
238 struct list_head free_event_queue;
239 struct list_head event_queue;
240 wait_queue_head_t event_wait;
241 spinlock_t event_queue_lock;
242 struct mutex get_event_lock;
243 int event_abort;
244
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530245 struct list_head ion_region_queue; /* protected by lock */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700246 struct audmp3_drv_operations drv_ops;
247
248 int eq_enable;
249 int eq_needs_commit;
250 audpp_cmd_cfg_object_params_eqalizer eq;
251 audpp_cmd_cfg_object_params_volume vol_pan;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530252 struct ion_client *client;
253 struct ion_handle *input_buff_handle;
254 struct ion_handle *output_buff_handle;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700255};
256
257static int auddec_dsp_config(struct audio *audio, int enable);
258static void audpp_cmd_cfg_adec_params(struct audio *audio);
259static void audpp_cmd_cfg_routing_mode(struct audio *audio);
260static void audplay_send_data(struct audio *audio, unsigned needed);
261static void audplay_config_hostpcm(struct audio *audio);
262static void audplay_buffer_refresh(struct audio *audio);
263static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
264static void audmp3_post_event(struct audio *audio, int type,
265 union msm_audio_event_payload payload);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530266static unsigned long audmp3_ion_fixup(struct audio *audio, void *addr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700267 unsigned long len, int ref_up);
268
269static int rmt_put_resource(struct audio *audio)
270{
271 struct aud_codec_config_cmd cmd;
272 unsigned short client_idx;
273
274 cmd.cmd_id = RM_CMD_AUD_CODEC_CFG;
275 cmd.client_id = RM_AUD_CLIENT_ID;
276 cmd.task_id = audio->dec_id;
277 cmd.enable = RMT_DISABLE;
278 cmd.dec_type = AUDDEC_DEC_MP3;
279 client_idx = ((cmd.client_id << 8) | cmd.task_id);
280
281 return put_adsp_resource(client_idx, &cmd, sizeof(cmd));
282}
283
284static int rmt_get_resource(struct audio *audio)
285{
286 struct aud_codec_config_cmd cmd;
287 unsigned short client_idx;
288
289 cmd.cmd_id = RM_CMD_AUD_CODEC_CFG;
290 cmd.client_id = RM_AUD_CLIENT_ID;
291 cmd.task_id = audio->dec_id;
292 cmd.enable = RMT_ENABLE;
293 cmd.dec_type = AUDDEC_DEC_MP3;
294 client_idx = ((cmd.client_id << 8) | cmd.task_id);
295
296 return get_adsp_resource(client_idx, &cmd, sizeof(cmd));
297}
298
299/* must be called with audio->lock held */
300static int audio_enable(struct audio *audio)
301{
302 struct audmgr_config cfg;
303 int rc;
304
305 MM_DBG("\n"); /* Macro prints the file name and function */
306
307 if (audio->enabled)
308 return 0;
309
310 if (audio->rmt_resource_released == 1) {
311 audio->rmt_resource_released = 0;
312 rc = rmt_get_resource(audio);
313 if (rc) {
314 MM_ERR("ADSP resources are not available for MP3 \
315 session 0x%08x on decoder: %d\n Ignoring \
316 error and going ahead with the playback\n",
317 (int)audio, audio->dec_id);
318 }
319 }
320
321 audio->dec_state = MSM_AUD_DECODER_STATE_NONE;
322 audio->out_tail = 0;
323 audio->out_needed = 0;
324
325 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
326 cfg.tx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
327 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_48000;
328 cfg.def_method = RPC_AUD_DEF_METHOD_PLAYBACK;
329 cfg.codec = RPC_AUD_DEF_CODEC_MP3;
330 cfg.snd_method = RPC_SND_METHOD_MIDI;
331
332 rc = audmgr_enable(&audio->audmgr, &cfg);
=Chaithanya Krishna Bacharajub5c4e982012-12-06 09:53:18 +0530333 if (rc < 0) {
334 msm_adsp_dump(audio->audplay);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700335 return rc;
=Chaithanya Krishna Bacharajub5c4e982012-12-06 09:53:18 +0530336 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700337 }
338
339 if (msm_adsp_enable(audio->audplay)) {
340 MM_ERR("msm_adsp_enable(audplay) failed\n");
341 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
342 audmgr_disable(&audio->audmgr);
343 return -ENODEV;
344 }
345
346 if (audpp_enable(audio->dec_id, audio_dsp_event, audio)) {
347 MM_ERR("audpp_enable() failed\n");
348 msm_adsp_disable(audio->audplay);
349 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
350 audmgr_disable(&audio->audmgr);
351 return -ENODEV;
352 }
353
354 audio->enabled = 1;
355 return 0;
356}
357
358/* must be called with audio->lock held */
359static int audio_disable(struct audio *audio)
360{
361 int rc = 0;
362 MM_DBG("\n"); /* Macro prints the file name and function */
363 if (audio->enabled) {
364 audio->enabled = 0;
365 audio->dec_state = MSM_AUD_DECODER_STATE_NONE;
366 auddec_dsp_config(audio, 0);
367 rc = wait_event_interruptible_timeout(audio->wait,
368 audio->dec_state != MSM_AUD_DECODER_STATE_NONE,
369 msecs_to_jiffies(MSM_AUD_DECODER_WAIT_MS));
370 if (rc == 0)
371 rc = -ETIMEDOUT;
372 else if (audio->dec_state != MSM_AUD_DECODER_STATE_CLOSE)
373 rc = -EFAULT;
374 else
375 rc = 0;
Manish Dewangan89a9f232012-02-09 17:14:40 +0530376 audio->stopped = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700377 wake_up(&audio->write_wait);
378 wake_up(&audio->read_wait);
379 msm_adsp_disable(audio->audplay);
380 audpp_disable(audio->dec_id, audio);
=Chaithanya Krishna Bacharajub5c4e982012-12-06 09:53:18 +0530381 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
382 rc = audmgr_disable(&audio->audmgr);
383 if (rc < 0)
384 msm_adsp_dump(audio->audplay);
385 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700386 audio->out_needed = 0;
387 rmt_put_resource(audio);
388 audio->rmt_resource_released = 1;
389 }
390 return rc;
391}
392
393/* ------------------- dsp --------------------- */
394static void audmp3_async_pcm_buf_update(struct audio *audio, uint32_t *payload)
395{
396 unsigned long flags;
397 union msm_audio_event_payload event_payload;
398 struct audmp3_buffer_node *filled_buf;
399 uint8_t index;
400
401 if (audio->rflush)
402 return;
403
404 spin_lock_irqsave(&audio->dsp_lock, flags);
405 for (index = 0; index < payload[1]; index++) {
406 BUG_ON(list_empty(&audio->in_queue));
407 filled_buf = list_first_entry(&audio->in_queue,
408 struct audmp3_buffer_node, list);
409 if (filled_buf->paddr == payload[2 + index * 2]) {
410 list_del(&filled_buf->list);
411 event_payload.aio_buf = filled_buf->buf;
412 event_payload.aio_buf.data_len =
413 payload[3 + index * 2];
414 MM_DBG("pcm buf %p data_len %d\n", filled_buf,
415 event_payload.aio_buf.data_len);
416 audmp3_post_event(audio, AUDIO_EVENT_READ_DONE,
417 event_payload);
418 kfree(filled_buf);
419 } else {
420 MM_ERR("expected=%lx ret=%x\n", filled_buf->paddr,
421 payload[2 + index * 2]);
422 break;
423 }
424 }
425
426 audio->drv_status &= ~ADRV_STATUS_IBUF_GIVEN;
427 audio->drv_ops.buffer_refresh(audio);
428 spin_unlock_irqrestore(&audio->dsp_lock, flags);
429
430}
431
432static void audio_update_pcm_buf_entry(struct audio *audio, uint32_t *payload)
433{
434 uint8_t index;
435 unsigned long flags;
436
437 if (audio->rflush)
438 return;
439
440 spin_lock_irqsave(&audio->dsp_lock, flags);
441 for (index = 0; index < payload[1]; index++) {
442 if (audio->in[audio->fill_next].addr ==
443 payload[2 + index * 2]) {
444 MM_DBG("in[%d] ready\n", audio->fill_next);
445 audio->in[audio->fill_next].used =
446 payload[3 + index * 2];
447 if ((++audio->fill_next) == audio->pcm_buf_count)
448 audio->fill_next = 0;
449
450 } else {
451 MM_ERR("expected=%x ret=%x\n",
452 audio->in[audio->fill_next].addr,
453 payload[2 + index * 2]);
454 break;
455 }
456 }
457 if (audio->in[audio->fill_next].used == 0) {
458 audio->drv_ops.buffer_refresh(audio);
459 } else {
460 MM_DBG("read cannot keep up\n");
461 audio->buf_refresh = 1;
462 }
463 wake_up(&audio->read_wait);
464 spin_unlock_irqrestore(&audio->dsp_lock, flags);
465
466}
467
468static void audplay_dsp_event(void *data, unsigned id, size_t len,
469 void (*getevent) (void *ptr, size_t len))
470{
471 struct audio *audio = data;
472 uint32_t msg[28];
473 getevent(msg, sizeof(msg));
474
475 MM_DBG("msg_id=%x\n", id);
476
477 switch (id) {
478 case AUDPLAY_MSG_DEC_NEEDS_DATA:
479 audio->drv_ops.send_data(audio, 1);
480 break;
481
482 case AUDPLAY_MSG_BUFFER_UPDATE:
483 audio->drv_ops.pcm_buf_update(audio, msg);
484 break;
485
486 case ADSP_MESSAGE_ID:
487 MM_DBG("Received ADSP event: module enable(audplaytask)\n");
488 break;
489
490 default:
491 MM_ERR("unexpected message from decoder \n");
492 break;
493 }
494}
495
496static void audio_dsp_event(void *private, unsigned id, uint16_t *msg)
497{
498 struct audio *audio = private;
499
500 switch (id) {
501 case AUDPP_MSG_STATUS_MSG:{
502 unsigned status = msg[1];
503
504 switch (status) {
505 case AUDPP_DEC_STATUS_SLEEP: {
506 uint16_t reason = msg[2];
507 MM_DBG("decoder status: sleep reason=0x%04x\n",
508 reason);
509 if ((reason == AUDPP_MSG_REASON_MEM)
510 || (reason ==
511 AUDPP_MSG_REASON_NODECODER)) {
512 audio->dec_state =
513 MSM_AUD_DECODER_STATE_FAILURE;
514 wake_up(&audio->wait);
515 } else if (reason == AUDPP_MSG_REASON_NONE) {
516 /* decoder is in disable state */
517 audio->dec_state =
518 MSM_AUD_DECODER_STATE_CLOSE;
519 wake_up(&audio->wait);
520 }
521 break;
522 }
523 case AUDPP_DEC_STATUS_INIT:
524 MM_DBG("decoder status: init \n");
525 if (audio->pcm_feedback)
526 audpp_cmd_cfg_routing_mode(audio);
527 else
528 audpp_cmd_cfg_adec_params(audio);
529 break;
530
531 case AUDPP_DEC_STATUS_CFG:
532 MM_DBG("decoder status: cfg \n");
533 break;
534 case AUDPP_DEC_STATUS_PLAY:
535 MM_DBG("decoder status: play \n");
536 if (audio->pcm_feedback) {
537 audplay_config_hostpcm(audio);
538 audio->drv_ops.buffer_refresh(audio);
539 }
540 audio->dec_state =
541 MSM_AUD_DECODER_STATE_SUCCESS;
542 wake_up(&audio->wait);
543 break;
544 default:
545 MM_ERR("unknown decoder status \n");
546 break;
547 }
548 break;
549 }
550 case AUDPP_MSG_CFG_MSG:
551 if (msg[0] == AUDPP_MSG_ENA_ENA) {
552 MM_DBG("CFG_MSG ENABLE\n");
553 auddec_dsp_config(audio, 1);
554 audio->out_needed = 0;
555 audio->running = 1;
556 audpp_dsp_set_vol_pan(audio->dec_id, &audio->vol_pan);
557 audpp_dsp_set_eq(audio->dec_id, audio->eq_enable,
558 &audio->eq);
559 audpp_avsync(audio->dec_id, 22050);
560 } else if (msg[0] == AUDPP_MSG_ENA_DIS) {
561 MM_DBG("CFG_MSG DISABLE\n");
562 audpp_avsync(audio->dec_id, 0);
563 audio->running = 0;
564 } else {
565 MM_DBG("CFG_MSG %d?\n", msg[0]);
566 }
567 break;
568 case AUDPP_MSG_ROUTING_ACK:
569 MM_DBG("ROUTING_ACK mode=%d\n", msg[1]);
570 audpp_cmd_cfg_adec_params(audio);
571 break;
572
573 case AUDPP_MSG_FLUSH_ACK:
574 MM_DBG("FLUSH_ACK\n");
575 audio->wflush = 0;
576 audio->rflush = 0;
577 wake_up(&audio->write_wait);
578 if (audio->pcm_feedback)
579 audio->drv_ops.buffer_refresh(audio);
580 break;
581
582 case AUDPP_MSG_PCMDMAMISSED:
583 MM_DBG("PCMDMAMISSED\n");
584 audio->teos = 1;
585 wake_up(&audio->write_wait);
586 break;
587
588 default:
589 MM_ERR("UNKNOWN (%d)\n", id);
590 }
591
592}
593
594
595struct msm_adsp_ops audplay_adsp_ops = {
596 .event = audplay_dsp_event,
597};
598
599
600#define audplay_send_queue0(audio, cmd, len) \
601 msm_adsp_write(audio->audplay, audio->queue_id, \
602 cmd, len)
603
604static int auddec_dsp_config(struct audio *audio, int enable)
605{
606 u16 cfg_dec_cmd[AUDPP_CMD_CFG_DEC_TYPE_LEN / sizeof(unsigned short)];
607
608 memset(cfg_dec_cmd, 0, sizeof(cfg_dec_cmd));
609
610 cfg_dec_cmd[0] = AUDPP_CMD_CFG_DEC_TYPE;
611 if (enable)
612 cfg_dec_cmd[1 + audio->dec_id] = AUDPP_CMD_UPDATDE_CFG_DEC |
613 AUDPP_CMD_ENA_DEC_V | AUDDEC_DEC_MP3;
614 else
615 cfg_dec_cmd[1 + audio->dec_id] = AUDPP_CMD_UPDATDE_CFG_DEC |
616 AUDPP_CMD_DIS_DEC_V;
617
618 return audpp_send_queue1(&cfg_dec_cmd, sizeof(cfg_dec_cmd));
619}
620
621static void audpp_cmd_cfg_adec_params(struct audio *audio)
622{
623 audpp_cmd_cfg_adec_params_mp3 cmd;
624
625 memset(&cmd, 0, sizeof(cmd));
626 cmd.common.cmd_id = AUDPP_CMD_CFG_ADEC_PARAMS;
627 cmd.common.length = AUDPP_CMD_CFG_ADEC_PARAMS_MP3_LEN;
628 cmd.common.dec_id = audio->dec_id;
629 cmd.common.input_sampling_frequency = audio->out_sample_rate;
630
631 audpp_send_queue2(&cmd, sizeof(cmd));
632}
633
634static void audpp_cmd_cfg_routing_mode(struct audio *audio)
635{
636 struct audpp_cmd_routing_mode cmd;
637 MM_DBG("\n"); /* Macro prints the file name and function */
638 memset(&cmd, 0, sizeof(cmd));
639 cmd.cmd_id = AUDPP_CMD_ROUTING_MODE;
640 cmd.object_number = audio->dec_id;
641 if (audio->pcm_feedback)
642 cmd.routing_mode = ROUTING_MODE_FTRT;
643 else
644 cmd.routing_mode = ROUTING_MODE_RT;
645
646 audpp_send_queue1(&cmd, sizeof(cmd));
647}
648
649static int audplay_dsp_send_data_avail(struct audio *audio,
650 unsigned idx, unsigned len)
651{
652 struct audplay_cmd_bitstream_data_avail_nt2 cmd;
653
654 cmd.cmd_id = AUDPLAY_CMD_BITSTREAM_DATA_AVAIL_NT2;
655 if (audio->mfield)
656 cmd.decoder_id = AUDMP3_METAFIELD_MASK |
657 (audio->out[idx].mfield_sz >> 1);
658 else
659 cmd.decoder_id = audio->dec_id;
660 cmd.buf_ptr = audio->out[idx].addr;
661 cmd.buf_size = len/2;
662 cmd.partition_number = 0;
663 /* complete all the writes to the input buffer */
664 wmb();
665 return audplay_send_queue0(audio, &cmd, sizeof(cmd));
666}
667
668/* Caller holds irq_lock */
669static void audmp3_async_buffer_refresh(struct audio *audio)
670{
671 struct audplay_cmd_buffer_refresh refresh_cmd;
672 struct audmp3_buffer_node *next_buf;
673
674 if (!audio->running ||
675 audio->drv_status & ADRV_STATUS_IBUF_GIVEN)
676 return;
677
678 if (!list_empty(&audio->in_queue)) {
679 next_buf = list_first_entry(&audio->in_queue,
680 struct audmp3_buffer_node, list);
681 if (!next_buf)
682 return;
683 MM_DBG("next buf %p phy %lx len %d\n", next_buf,
684 next_buf->paddr, next_buf->buf.buf_len);
685 refresh_cmd.cmd_id = AUDPLAY_CMD_BUFFER_REFRESH;
686 refresh_cmd.num_buffers = 1;
687 refresh_cmd.buf0_address = next_buf->paddr;
688 refresh_cmd.buf0_length = next_buf->buf.buf_len -
689 (next_buf->buf.buf_len % 576) +
690 (audio->mfield ? 24 : 0); /* Mp3 frame size */
691 refresh_cmd.buf_read_count = 0;
692 audio->drv_status |= ADRV_STATUS_IBUF_GIVEN;
693 (void) audplay_send_queue0(audio, &refresh_cmd,
694 sizeof(refresh_cmd));
695 }
696
697}
698
699static void audplay_buffer_refresh(struct audio *audio)
700{
701 struct audplay_cmd_buffer_refresh refresh_cmd;
702
703 refresh_cmd.cmd_id = AUDPLAY_CMD_BUFFER_REFRESH;
704 refresh_cmd.num_buffers = 1;
705 refresh_cmd.buf0_address = audio->in[audio->fill_next].addr;
706 refresh_cmd.buf0_length = audio->in[audio->fill_next].size -
707 (audio->in[audio->fill_next].size % 576) +
708 (audio->mfield ? 24 : 0); /* Mp3 frame size */
709 refresh_cmd.buf_read_count = 0;
710 MM_DBG("buf0_addr=%x buf0_len=%d\n", refresh_cmd.buf0_address,
711 refresh_cmd.buf0_length);
712 (void)audplay_send_queue0(audio, &refresh_cmd, sizeof(refresh_cmd));
713}
714
715static void audplay_config_hostpcm(struct audio *audio)
716{
717 struct audplay_cmd_hpcm_buf_cfg cfg_cmd;
718
719 MM_DBG("\n"); /* Macro prints the file name and function */
720 cfg_cmd.cmd_id = AUDPLAY_CMD_HPCM_BUF_CFG;
721 cfg_cmd.max_buffers = 1;
722 cfg_cmd.byte_swap = 0;
723 cfg_cmd.hostpcm_config = (0x8000) | (0x4000);
724 cfg_cmd.feedback_frequency = 1;
725 cfg_cmd.partition_number = 0;
726 (void)audplay_send_queue0(audio, &cfg_cmd, sizeof(cfg_cmd));
727
728}
729
730static void audmp3_async_send_data(struct audio *audio, unsigned needed)
731{
732 unsigned long flags;
733
734 spin_lock_irqsave(&audio->dsp_lock, flags);
735 if (!audio->running)
736 goto done;
737
738 if (needed && !audio->wflush) {
739 audio->out_needed = 1;
740 if (audio->drv_status & ADRV_STATUS_OBUF_GIVEN) {
741 /* pop one node out of queue */
742 union msm_audio_event_payload payload;
743 struct audmp3_buffer_node *used_buf;
744
745 MM_DBG("consumed\n");
746 BUG_ON(list_empty(&audio->out_queue));
747 used_buf = list_first_entry(&audio->out_queue,
748 struct audmp3_buffer_node, list);
749 list_del(&used_buf->list);
750 payload.aio_buf = used_buf->buf;
751 audmp3_post_event(audio, AUDIO_EVENT_WRITE_DONE,
752 payload);
753 kfree(used_buf);
754 audio->drv_status &= ~ADRV_STATUS_OBUF_GIVEN;
755 }
756
757 }
758
759 if (audio->out_needed) {
760 struct audmp3_buffer_node *next_buf;
761 struct audplay_cmd_bitstream_data_avail_nt2 cmd;
762 if (!list_empty(&audio->out_queue)) {
763 next_buf = list_first_entry(&audio->out_queue,
764 struct audmp3_buffer_node, list);
765 MM_DBG("next_buf %p\n", next_buf);
766 if (next_buf) {
767 MM_DBG("next buf phy %lx len %d\n",
768 next_buf->paddr,
769 next_buf->buf.data_len);
770
771 cmd.cmd_id =
772 AUDPLAY_CMD_BITSTREAM_DATA_AVAIL_NT2;
773 if (audio->mfield)
774 cmd.decoder_id = AUDMP3_METAFIELD_MASK |
775 (next_buf->buf.mfield_sz >> 1);
776 else
777 cmd.decoder_id = audio->dec_id;
778 cmd.buf_ptr = (unsigned) next_buf->paddr;
779 cmd.buf_size = next_buf->buf.data_len >> 1;
780 cmd.partition_number = 0;
781 /* complete the writes to the input buffer */
782 wmb();
783 audplay_send_queue0(audio, &cmd, sizeof(cmd));
784 audio->out_needed = 0;
785 audio->drv_status |= ADRV_STATUS_OBUF_GIVEN;
786 }
787 }
788 }
789
790done:
791 spin_unlock_irqrestore(&audio->dsp_lock, flags);
792}
793
794static void audplay_send_data(struct audio *audio, unsigned needed)
795{
796 struct buffer *frame;
797 unsigned long flags;
798
799 spin_lock_irqsave(&audio->dsp_lock, flags);
800 if (!audio->running)
801 goto done;
802
803 if (needed && !audio->wflush) {
804 /* We were called from the callback because the DSP
805 * requested more data. Note that the DSP does want
806 * more data, and if a buffer was in-flight, mark it
807 * as available (since the DSP must now be done with
808 * it).
809 */
810 audio->out_needed = 1;
811 frame = audio->out + audio->out_tail;
812 if (frame->used == 0xffffffff) {
813 MM_DBG("frame %d free\n", audio->out_tail);
814 frame->used = 0;
815 audio->out_tail ^= 1;
816 wake_up(&audio->write_wait);
817 }
818 }
819
820 if (audio->out_needed) {
821 /* If the DSP currently wants data and we have a
822 * buffer available, we will send it and reset
823 * the needed flag. We'll mark the buffer as in-flight
824 * so that it won't be recycled until the next buffer
825 * is requested
826 */
827
828 frame = audio->out + audio->out_tail;
829 if (frame->used) {
830 BUG_ON(frame->used == 0xffffffff);
831 MM_DBG("frame %d busy\n", audio->out_tail);
832 audplay_dsp_send_data_avail(audio, audio->out_tail,
833 frame->used);
834 frame->used = 0xffffffff;
835 audio->out_needed = 0;
836 }
837 }
838done:
839 spin_unlock_irqrestore(&audio->dsp_lock, flags);
840}
841
842/* ------------------- device --------------------- */
843static void audmp3_async_flush(struct audio *audio)
844{
845 struct audmp3_buffer_node *buf_node;
846 struct list_head *ptr, *next;
847 union msm_audio_event_payload payload;
Chaithanya Krishna Bacharaju221f7992012-05-16 09:32:54 +0530848 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700849
Chaithanya Krishna Bacharaju221f7992012-05-16 09:32:54 +0530850 spin_lock_irqsave(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700851 MM_DBG("\n"); /* Macro prints the file name and function */
852 list_for_each_safe(ptr, next, &audio->out_queue) {
853 buf_node = list_entry(ptr, struct audmp3_buffer_node, list);
854 list_del(&buf_node->list);
855 payload.aio_buf = buf_node->buf;
856 audmp3_post_event(audio, AUDIO_EVENT_WRITE_DONE,
857 payload);
858 kfree(buf_node);
859 }
860 audio->drv_status &= ~ADRV_STATUS_OBUF_GIVEN;
861 audio->out_needed = 0;
862 atomic_set(&audio->out_bytes, 0);
Chaithanya Krishna Bacharaju221f7992012-05-16 09:32:54 +0530863 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700864}
865
866static void audio_flush(struct audio *audio)
867{
Manish Dewangana4f1df02012-02-08 17:06:54 +0530868 unsigned long flags;
869
870 spin_lock_irqsave(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700871 audio->out[0].used = 0;
872 audio->out[1].used = 0;
873 audio->out_head = 0;
874 audio->out_tail = 0;
875 audio->reserved = 0;
876 audio->out_needed = 0;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530877 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700878 atomic_set(&audio->out_bytes, 0);
879}
880
881static void audmp3_async_flush_pcm_buf(struct audio *audio)
882{
883 struct audmp3_buffer_node *buf_node;
884 struct list_head *ptr, *next;
885 union msm_audio_event_payload payload;
886
887 MM_DBG("\n"); /* Macro prints the file name and function */
888 list_for_each_safe(ptr, next, &audio->in_queue) {
889 buf_node = list_entry(ptr, struct audmp3_buffer_node, list);
890 list_del(&buf_node->list);
891 payload.aio_buf = buf_node->buf;
892 payload.aio_buf.data_len = 0;
893 audmp3_post_event(audio, AUDIO_EVENT_READ_DONE,
894 payload);
895 kfree(buf_node);
896 }
897 audio->drv_status &= ~ADRV_STATUS_IBUF_GIVEN;
898
899}
900
901static void audio_flush_pcm_buf(struct audio *audio)
902{
903 uint8_t index;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530904 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700905
Manish Dewangana4f1df02012-02-08 17:06:54 +0530906 spin_lock_irqsave(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700907 for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
908 audio->in[index].used = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700909 audio->buf_refresh = 0;
910 audio->read_next = 0;
911 audio->fill_next = 0;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530912 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700913}
914
915static void audio_ioport_reset(struct audio *audio)
916{
917 if (audio->drv_status & ADRV_STATUS_AIO_INTF) {
918 /* If fsync is in progress, make sure
919 * return value of fsync indicates
920 * abort due to flush
921 */
922 if (audio->drv_status & ADRV_STATUS_FSYNC) {
923 MM_DBG("fsync in progress\n");
924 wake_up(&audio->write_wait);
925 mutex_lock(&audio->write_lock);
926 audio->drv_ops.out_flush(audio);
927 mutex_unlock(&audio->write_lock);
928 } else
929 audio->drv_ops.out_flush(audio);
930 audio->drv_ops.in_flush(audio);
931 } else {
932 /* Make sure read/write thread are free from
933 * sleep and knowing that system is not able
934 * to process io request at the moment
935 */
936 wake_up(&audio->write_wait);
937 mutex_lock(&audio->write_lock);
938 audio->drv_ops.out_flush(audio);
939 mutex_unlock(&audio->write_lock);
940 wake_up(&audio->read_wait);
941 mutex_lock(&audio->read_lock);
942 audio->drv_ops.in_flush(audio);
943 mutex_unlock(&audio->read_lock);
944 }
945}
946
947static int audmp3_events_pending(struct audio *audio)
948{
949 unsigned long flags;
950 int empty;
951
952 spin_lock_irqsave(&audio->event_queue_lock, flags);
953 empty = !list_empty(&audio->event_queue);
954 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
955 return empty || audio->event_abort;
956}
957
958static void audmp3_reset_event_queue(struct audio *audio)
959{
960 unsigned long flags;
961 struct audmp3_event *drv_evt;
962 struct list_head *ptr, *next;
963
964 spin_lock_irqsave(&audio->event_queue_lock, flags);
965 list_for_each_safe(ptr, next, &audio->event_queue) {
966 drv_evt = list_first_entry(&audio->event_queue,
967 struct audmp3_event, list);
968 list_del(&drv_evt->list);
969 kfree(drv_evt);
970 }
971 list_for_each_safe(ptr, next, &audio->free_event_queue) {
972 drv_evt = list_first_entry(&audio->free_event_queue,
973 struct audmp3_event, list);
974 list_del(&drv_evt->list);
975 kfree(drv_evt);
976 }
977 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
978
979 return;
980}
981
982static long audmp3_process_event_req(struct audio *audio, void __user *arg)
983{
984 long rc;
985 struct msm_audio_event usr_evt;
986 struct audmp3_event *drv_evt = NULL;
987 int timeout;
988 unsigned long flags;
989
990 if (copy_from_user(&usr_evt, arg, sizeof(struct msm_audio_event)))
991 return -EFAULT;
992
993 timeout = (int) usr_evt.timeout_ms;
994
995 if (timeout > 0) {
996 rc = wait_event_interruptible_timeout(
997 audio->event_wait, audmp3_events_pending(audio),
998 msecs_to_jiffies(timeout));
999 if (rc == 0)
1000 return -ETIMEDOUT;
1001 } else {
1002 rc = wait_event_interruptible(
1003 audio->event_wait, audmp3_events_pending(audio));
1004 }
1005
1006 if (rc < 0)
1007 return rc;
1008
1009 if (audio->event_abort) {
1010 audio->event_abort = 0;
1011 return -ENODEV;
1012 }
1013
1014 rc = 0;
1015
1016 spin_lock_irqsave(&audio->event_queue_lock, flags);
1017 if (!list_empty(&audio->event_queue)) {
1018 drv_evt = list_first_entry(&audio->event_queue,
1019 struct audmp3_event, list);
1020 list_del(&drv_evt->list);
1021 }
1022 if (drv_evt) {
1023 usr_evt.event_type = drv_evt->event_type;
1024 usr_evt.event_payload = drv_evt->payload;
1025 list_add_tail(&drv_evt->list, &audio->free_event_queue);
1026 } else
1027 rc = -1;
1028 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
1029
1030 if (drv_evt->event_type == AUDIO_EVENT_WRITE_DONE ||
1031 drv_evt->event_type == AUDIO_EVENT_READ_DONE) {
1032 mutex_lock(&audio->lock);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301033 audmp3_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001034 drv_evt->payload.aio_buf.buf_len, 0);
1035 mutex_unlock(&audio->lock);
1036 }
1037
1038 /* order reads from the output buffer */
1039 if (drv_evt->event_type == AUDIO_EVENT_READ_DONE)
1040 rmb();
1041
1042 if (!rc && copy_to_user(arg, &usr_evt, sizeof(usr_evt)))
1043 rc = -EFAULT;
1044
1045 return rc;
1046}
1047
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301048static int audmp3_ion_check(struct audio *audio,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001049 void *vaddr, unsigned long len)
1050{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301051 struct audmp3_ion_region *region_elt;
1052 struct audmp3_ion_region t = { .vaddr = vaddr, .len = len };
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001053
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301054 list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001055 if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
1056 OVERLAPS(region_elt, &t)) {
1057 MM_ERR("region (vaddr %p len %ld)"
1058 " clashes with registered region"
1059 " (vaddr %p paddr %p len %ld)\n",
1060 vaddr, len,
1061 region_elt->vaddr,
1062 (void *)region_elt->paddr,
1063 region_elt->len);
1064 return -EINVAL;
1065 }
1066 }
1067
1068 return 0;
1069}
1070
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301071static int audmp3_ion_add(struct audio *audio,
1072 struct msm_audio_ion_info *info)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001073{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301074 ion_phys_addr_t paddr;
1075 size_t len;
1076 unsigned long kvaddr;
1077 struct audmp3_ion_region *region;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001078 int rc = -EINVAL;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301079 struct ion_handle *handle;
1080 unsigned long ionflag;
1081 void *temp_ptr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001082
1083 MM_DBG("\n"); /* Macro prints the file name and function */
1084 region = kmalloc(sizeof(*region), GFP_KERNEL);
1085
1086 if (!region) {
1087 rc = -ENOMEM;
1088 goto end;
1089 }
1090
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301091 handle = ion_import_dma_buf(audio->client, info->fd);
1092 if (IS_ERR_OR_NULL(handle)) {
1093 pr_err("%s: could not get handle of the given fd\n", __func__);
1094 goto import_error;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001095 }
1096
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301097 rc = ion_handle_get_flags(audio->client, handle, &ionflag);
1098 if (rc) {
1099 pr_err("%s: could not get flags for the handle\n", __func__);
1100 goto flag_error;
1101 }
1102
Mitchel Humpherys911b4b72012-09-12 14:42:50 -07001103 temp_ptr = ion_map_kernel(audio->client, handle);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301104 if (IS_ERR_OR_NULL(temp_ptr)) {
1105 pr_err("%s: could not get virtual address\n", __func__);
1106 goto map_error;
1107 }
1108 kvaddr = (unsigned long) temp_ptr;
1109
1110 rc = ion_phys(audio->client, handle, &paddr, &len);
1111 if (rc) {
1112 pr_err("%s: could not get physical address\n", __func__);
1113 goto ion_error;
1114 }
1115
1116 rc = audmp3_ion_check(audio, info->vaddr, len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001117 if (rc < 0) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301118 MM_ERR("audpcm_ion_check failed\n");
1119 goto ion_error;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001120 }
1121
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301122 region->handle = handle;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001123 region->vaddr = info->vaddr;
1124 region->fd = info->fd;
1125 region->paddr = paddr;
1126 region->kvaddr = kvaddr;
1127 region->len = len;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001128 region->ref_cnt = 0;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301129 MM_DBG("[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
1130 audio, region->paddr, region->vaddr,
1131 region->len, region->kvaddr);
1132 list_add_tail(&region->list, &audio->ion_region_queue);
1133 return rc;
1134
1135ion_error:
1136 ion_unmap_kernel(audio->client, handle);
1137map_error:
1138flag_error:
1139 ion_free(audio->client, handle);
1140import_error:
1141 kfree(region);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001142end:
1143 return rc;
1144}
1145
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301146static int audmp3_ion_remove(struct audio *audio,
1147 struct msm_audio_ion_info *info)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001148{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301149 struct audmp3_ion_region *region;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001150 struct list_head *ptr, *next;
1151 int rc = -EINVAL;
1152
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301153 list_for_each_safe(ptr, next, &audio->ion_region_queue) {
1154 region = list_entry(ptr, struct audmp3_ion_region, list);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001155
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301156 if (region != NULL && (region->fd == info->fd) &&
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001157 (region->vaddr == info->vaddr)) {
1158 if (region->ref_cnt) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301159 MM_DBG("%s[%p]:region %p in use ref_cnt %d\n",
1160 __func__, audio, region,
1161 region->ref_cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001162 break;
1163 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301164 MM_DBG("remove region fd %d vaddr %p\n",
1165 info->fd, info->vaddr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001166 list_del(&region->list);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301167 ion_unmap_kernel(audio->client, region->handle);
1168 ion_free(audio->client, region->handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001169 kfree(region);
1170 rc = 0;
1171 break;
1172 }
1173 }
1174
1175 return rc;
1176}
1177
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301178static int audmp3_ion_lookup_vaddr(struct audio *audio, void *addr,
1179 unsigned long len, struct audmp3_ion_region **region)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001180{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301181 struct audmp3_ion_region *region_elt;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001182 int match_count = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001183 *region = NULL;
1184
1185 /* returns physical address or zero */
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301186 list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001187 if (addr >= region_elt->vaddr &&
1188 addr < region_elt->vaddr + region_elt->len &&
1189 addr + len <= region_elt->vaddr + region_elt->len) {
1190 /* offset since we could pass vaddr inside a registerd
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301191 * ion buffer
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001192 */
1193
1194 match_count++;
1195 if (!*region)
1196 *region = region_elt;
1197 }
1198 }
1199
1200 if (match_count > 1) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301201 MM_ERR("%s[%p]:multiple hits for vaddr %p, len %ld\n",
1202 __func__, audio, addr, len);
1203 list_for_each_entry(region_elt, &audio->ion_region_queue,
1204 list) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001205 if (addr >= region_elt->vaddr &&
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301206 addr < region_elt->vaddr + region_elt->len &&
1207 addr + len <= region_elt->vaddr + region_elt->len)
1208 MM_ERR("\t%s[%p]:%p, %ld --> %p\n",
1209 __func__, audio,
1210 region_elt->vaddr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001211 region_elt->len,
1212 (void *)region_elt->paddr);
1213 }
1214 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001215 return *region ? 0 : -1;
1216}
1217
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301218unsigned long audmp3_ion_fixup(struct audio *audio, void *addr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001219 unsigned long len, int ref_up)
1220{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301221 struct audmp3_ion_region *region;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001222 unsigned long paddr;
1223 int ret;
1224
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301225 ret = audmp3_ion_lookup_vaddr(audio, addr, len, &region);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001226 if (ret) {
1227 MM_ERR("lookup (%p, %ld) failed\n", addr, len);
1228 return 0;
1229 }
1230 if (ref_up)
1231 region->ref_cnt++;
1232 else
1233 region->ref_cnt--;
1234 MM_DBG("found region %p ref_cnt %d\n", region, region->ref_cnt);
1235 paddr = region->paddr + (addr - region->vaddr);
1236 return paddr;
1237}
1238
1239/* audio -> lock must be held at this point */
1240static int audmp3_aio_buf_add(struct audio *audio, unsigned dir,
1241 void __user *arg)
1242{
1243 unsigned long flags;
1244 struct audmp3_buffer_node *buf_node;
1245
1246 buf_node = kmalloc(sizeof(*buf_node), GFP_KERNEL);
1247
1248 if (!buf_node)
1249 return -ENOMEM;
1250
1251 if (copy_from_user(&buf_node->buf, arg, sizeof(buf_node->buf))) {
1252 kfree(buf_node);
1253 return -EFAULT;
1254 }
1255
1256 MM_DBG("node %p dir %x buf_addr %p buf_len %d data_len \
1257 %d\n", buf_node, dir,
1258 buf_node->buf.buf_addr, buf_node->buf.buf_len,
1259 buf_node->buf.data_len);
1260
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301261 buf_node->paddr = audmp3_ion_fixup(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001262 audio, buf_node->buf.buf_addr,
1263 buf_node->buf.buf_len, 1);
1264
1265 if (dir) {
1266 /* write */
1267 if (!buf_node->paddr ||
1268 (buf_node->paddr & 0x1) ||
1269 (buf_node->buf.data_len & 0x1) ||
1270 (!audio->pcm_feedback &&
1271 !buf_node->buf.data_len)) {
1272 kfree(buf_node);
1273 return -EINVAL;
1274 }
1275 spin_lock_irqsave(&audio->dsp_lock, flags);
1276 list_add_tail(&buf_node->list, &audio->out_queue);
1277 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1278 audio->drv_ops.send_data(audio, 0);
1279 } else {
1280 /* read */
1281 if (!buf_node->paddr ||
1282 (buf_node->paddr & 0x1) ||
1283 (buf_node->buf.buf_len < PCM_BUFSZ_MIN)) {
1284 kfree(buf_node);
1285 return -EINVAL;
1286 }
1287 spin_lock_irqsave(&audio->dsp_lock, flags);
1288 list_add_tail(&buf_node->list, &audio->in_queue);
1289 audio->drv_ops.buffer_refresh(audio);
1290 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1291 }
1292
1293 MM_DBG("Add buf_node %p paddr %lx\n", buf_node, buf_node->paddr);
1294
1295 return 0;
1296}
1297
1298static int audio_enable_eq(struct audio *audio, int enable)
1299{
1300 if (audio->eq_enable == enable && !audio->eq_needs_commit)
1301 return 0;
1302
1303 audio->eq_enable = enable;
1304
1305 if (audio->running) {
1306 audpp_dsp_set_eq(audio->dec_id, enable, &audio->eq);
1307 audio->eq_needs_commit = 0;
1308 }
1309 return 0;
1310}
1311
1312static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1313{
1314 struct audio *audio = file->private_data;
1315 int rc = -EINVAL;
1316 unsigned long flags = 0;
1317 uint16_t enable_mask;
1318 int enable;
1319 int prev_state;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301320 unsigned long ionflag = 0;
1321 ion_phys_addr_t addr = 0;
1322 struct ion_handle *handle = NULL;
1323 int len = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001324
1325 MM_DBG("cmd = %d\n", cmd);
1326
1327 if (cmd == AUDIO_GET_STATS) {
1328 struct msm_audio_stats stats;
1329 stats.byte_count = audpp_avsync_byte_count(audio->dec_id);
1330 stats.sample_count = audpp_avsync_sample_count(audio->dec_id);
1331 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
1332 return -EFAULT;
1333 return 0;
1334 }
1335
1336 switch (cmd) {
1337 case AUDIO_ENABLE_AUDPP:
1338 if (copy_from_user(&enable_mask, (void *) arg,
1339 sizeof(enable_mask))) {
1340 rc = -EFAULT;
1341 break;
1342 }
1343
1344 spin_lock_irqsave(&audio->dsp_lock, flags);
1345 enable = (enable_mask & EQ_ENABLE) ? 1 : 0;
1346 audio_enable_eq(audio, enable);
1347 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1348 rc = 0;
1349 break;
1350 case AUDIO_SET_VOLUME:
1351 spin_lock_irqsave(&audio->dsp_lock, flags);
1352 audio->vol_pan.volume = arg;
1353 if (audio->running)
1354 audpp_dsp_set_vol_pan(audio->dec_id, &audio->vol_pan);
1355 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1356 rc = 0;
1357 break;
1358
1359 case AUDIO_SET_PAN:
1360 spin_lock_irqsave(&audio->dsp_lock, flags);
1361 audio->vol_pan.pan = arg;
1362 if (audio->running)
1363 audpp_dsp_set_vol_pan(audio->dec_id, &audio->vol_pan);
1364 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1365 rc = 0;
1366 break;
1367
1368 case AUDIO_SET_EQ:
1369 prev_state = audio->eq_enable;
1370 audio->eq_enable = 0;
1371 if (copy_from_user(&audio->eq.num_bands, (void *) arg,
1372 sizeof(audio->eq) -
1373 (AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN + 2))) {
1374 rc = -EFAULT;
1375 break;
1376 }
1377 audio->eq_enable = prev_state;
1378 audio->eq_needs_commit = 1;
1379 rc = 0;
1380 break;
1381 }
1382
1383 if (-EINVAL != rc)
1384 return rc;
1385
1386 if (cmd == AUDIO_GET_EVENT) {
1387 MM_DBG(" AUDIO_GET_EVENT\n");
1388 if (mutex_trylock(&audio->get_event_lock)) {
1389 rc = audmp3_process_event_req(audio,
1390 (void __user *) arg);
1391 mutex_unlock(&audio->get_event_lock);
1392 } else
1393 rc = -EBUSY;
1394 return rc;
1395 }
1396
1397 if (cmd == AUDIO_ABORT_GET_EVENT) {
1398 audio->event_abort = 1;
1399 wake_up(&audio->event_wait);
1400 return 0;
1401 }
1402
1403 mutex_lock(&audio->lock);
1404 switch (cmd) {
1405 case AUDIO_START:
1406 MM_DBG("AUDIO_START\n");
1407 rc = audio_enable(audio);
1408 if (!rc) {
1409 rc = wait_event_interruptible_timeout(audio->wait,
1410 audio->dec_state != MSM_AUD_DECODER_STATE_NONE,
1411 msecs_to_jiffies(MSM_AUD_DECODER_WAIT_MS));
1412 MM_INFO("dec_state %d rc = %d\n", audio->dec_state, rc);
1413
1414 if (audio->dec_state != MSM_AUD_DECODER_STATE_SUCCESS)
1415 rc = -ENODEV;
1416 else
1417 rc = 0;
1418 }
1419 break;
1420 case AUDIO_STOP:
1421 MM_DBG("AUDIO_STOP\n");
1422 rc = audio_disable(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001423 audio_ioport_reset(audio);
1424 audio->stopped = 0;
1425 break;
1426 case AUDIO_FLUSH:
1427 MM_DBG("AUDIO_FLUSH\n");
1428 audio->rflush = 1;
1429 audio->wflush = 1;
1430 audio_ioport_reset(audio);
1431 if (audio->running) {
1432 audpp_flush(audio->dec_id);
1433 rc = wait_event_interruptible(audio->write_wait,
1434 !audio->wflush);
1435 if (rc < 0) {
1436 MM_ERR("AUDIO_FLUSH interrupted\n");
1437 rc = -EINTR;
1438 }
1439 } else {
1440 audio->rflush = 0;
1441 audio->wflush = 0;
1442 }
1443 break;
1444
1445 case AUDIO_SET_CONFIG: {
1446 struct msm_audio_config config;
1447 if (copy_from_user(&config, (void *) arg, sizeof(config))) {
1448 rc = -EFAULT;
1449 break;
1450 }
1451 if (config.channel_count == 1) {
1452 config.channel_count = AUDPP_CMD_PCM_INTF_MONO_V;
1453 } else if (config.channel_count == 2) {
1454 config.channel_count = AUDPP_CMD_PCM_INTF_STEREO_V;
1455 } else {
1456 rc = -EINVAL;
1457 break;
1458 }
1459 audio->mfield = config.meta_field;
1460 audio->out_sample_rate = config.sample_rate;
1461 audio->out_channel_mode = config.channel_count;
1462 rc = 0;
1463 break;
1464 }
1465 case AUDIO_GET_CONFIG: {
1466 struct msm_audio_config config;
1467 config.buffer_size = (audio->out_dma_sz >> 1);
1468 config.buffer_count = 2;
1469 config.sample_rate = audio->out_sample_rate;
1470 if (audio->out_channel_mode == AUDPP_CMD_PCM_INTF_MONO_V) {
1471 config.channel_count = 1;
1472 } else {
1473 config.channel_count = 2;
1474 }
1475 config.meta_field = 0;
1476 config.unused[0] = 0;
1477 config.unused[1] = 0;
1478 config.unused[2] = 0;
1479 if (copy_to_user((void *) arg, &config, sizeof(config))) {
1480 rc = -EFAULT;
1481 } else {
1482 rc = 0;
1483 }
1484 break;
1485 }
1486 case AUDIO_GET_PCM_CONFIG:{
1487 struct msm_audio_pcm_config config;
1488 config.pcm_feedback = audio->pcm_feedback;
1489 config.buffer_count = PCM_BUF_MAX_COUNT;
1490 config.buffer_size = PCM_BUFSZ_MIN;
1491 if (copy_to_user((void *)arg, &config,
1492 sizeof(config)))
1493 rc = -EFAULT;
1494 else
1495 rc = 0;
1496 break;
1497 }
1498 case AUDIO_SET_PCM_CONFIG:{
1499 struct msm_audio_pcm_config config;
1500 if (copy_from_user
1501 (&config, (void *)arg, sizeof(config))) {
1502 rc = -EFAULT;
1503 break;
1504 }
1505
1506 if (config.pcm_feedback != audio->pcm_feedback) {
1507 MM_ERR("Not sufficient permission to"
1508 "change the playback mode\n");
1509 rc = -EACCES;
1510 break;
1511 }
1512 if (audio->drv_status & ADRV_STATUS_AIO_INTF) {
1513 rc = 0;
1514 break;
1515 }
1516
1517 if ((config.buffer_count > PCM_BUF_MAX_COUNT) ||
1518 (config.buffer_count == 1))
1519 config.buffer_count = PCM_BUF_MAX_COUNT;
1520
1521 if (config.buffer_size < PCM_BUFSZ_MIN)
1522 config.buffer_size = PCM_BUFSZ_MIN;
1523
1524 /* Check if pcm feedback is required */
1525 if ((config.pcm_feedback) && (!audio->read_data)) {
1526 MM_DBG("allocate PCM buffer %d\n",
1527 config.buffer_count *
1528 config.buffer_size);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301529
1530 handle = ion_alloc(audio->client,
1531 (config.buffer_size *
1532 config.buffer_count),
Hanumant Singh7d72bad2012-08-29 18:39:44 -07001533 SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301534 if (IS_ERR_OR_NULL(handle)) {
1535 MM_ERR("Unable to alloc I/P buffs\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001536 rc = -ENOMEM;
1537 break;
1538 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301539
1540 audio->input_buff_handle = handle;
1541
1542 rc = ion_phys(audio->client ,
1543 handle, &addr, &len);
1544 if (rc) {
1545 MM_ERR("Invalid phy: %x sz: %x\n",
1546 (unsigned int) addr,
1547 (unsigned int) len);
1548 rc = -ENOMEM;
1549 break;
1550 } else {
1551 MM_INFO("Got valid phy: %x sz: %x\n",
1552 (unsigned int) audio->read_phys,
1553 (unsigned int) len);
1554 }
1555 audio->read_phys = (int32_t)addr;
1556
1557 rc = ion_handle_get_flags(audio->client,
1558 handle, &ionflag);
1559 if (rc) {
1560 MM_ERR("could not get flags\n");
1561 rc = -ENOMEM;
1562 break;
1563 }
1564
1565 audio->map_v_read = ion_map_kernel(
Mitchel Humpherys911b4b72012-09-12 14:42:50 -07001566 audio->client, handle);
Santosh Mardi0be3b8e2011-07-06 10:00:21 +05301567
1568 if (IS_ERR(audio->map_v_read)) {
1569 MM_ERR("map of read buf failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001570 rc = -ENOMEM;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301571 ion_free(audio->client, handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001572 } else {
1573 uint8_t index;
1574 uint32_t offset = 0;
Santosh Mardi0be3b8e2011-07-06 10:00:21 +05301575 audio->read_data =
Laura Abbott35111d32012-04-27 18:41:48 -07001576 audio->map_v_read;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001577 audio->buf_refresh = 0;
1578 audio->pcm_buf_count =
1579 config.buffer_count;
1580 audio->read_next = 0;
1581 audio->fill_next = 0;
1582
1583 for (index = 0;
1584 index < config.buffer_count;
1585 index++) {
1586 audio->in[index].data =
1587 audio->read_data + offset;
1588 audio->in[index].addr =
1589 audio->read_phys + offset;
1590 audio->in[index].size =
1591 config.buffer_size;
1592 audio->in[index].used = 0;
1593 offset += config.buffer_size;
1594 }
1595 rc = 0;
1596 MM_DBG("read buf: phy addr \
1597 0x%08x kernel addr 0x%08x\n",
1598 audio->read_phys,
1599 (int)audio->read_data);
1600 }
1601 } else {
1602 rc = 0;
1603 }
1604 break;
1605 }
1606 case AUDIO_PAUSE:
1607 MM_DBG("AUDIO_PAUSE %ld\n", arg);
1608 rc = audpp_pause(audio->dec_id, (int) arg);
1609 break;
1610
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301611 case AUDIO_REGISTER_ION: {
1612 struct msm_audio_ion_info info;
1613 MM_DBG("AUDIO_REGISTER_ION\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001614 if (copy_from_user(&info, (void *) arg, sizeof(info)))
1615 rc = -EFAULT;
1616 else
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301617 rc = audmp3_ion_add(audio, &info);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001618 break;
1619 }
1620
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301621 case AUDIO_DEREGISTER_ION: {
1622 struct msm_audio_ion_info info;
1623 MM_DBG("AUDIO_DEREGISTER_ION\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001624 if (copy_from_user(&info, (void *) arg, sizeof(info)))
1625 rc = -EFAULT;
1626 else
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301627 rc = audmp3_ion_remove(audio, &info);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001628 break;
1629 }
1630 case AUDIO_ASYNC_WRITE:
1631 if (audio->drv_status & ADRV_STATUS_FSYNC)
1632 rc = -EBUSY;
1633 else
1634 rc = audmp3_aio_buf_add(audio, 1, (void __user *) arg);
1635 break;
1636
1637 case AUDIO_ASYNC_READ:
1638 if (audio->pcm_feedback)
1639 rc = audmp3_aio_buf_add(audio, 0, (void __user *) arg);
1640 else
1641 rc = -EPERM;
1642 break;
1643
1644 default:
1645 rc = -EINVAL;
1646 }
1647 mutex_unlock(&audio->lock);
1648 return rc;
1649}
1650
1651/* Only useful in tunnel-mode */
1652int audmp3_async_fsync(struct audio *audio)
1653{
1654 int rc = 0;
1655
1656 MM_DBG("\n"); /* Macro prints the file name and function */
1657
1658 /* Blocking client sends more data */
1659 mutex_lock(&audio->lock);
1660 audio->drv_status |= ADRV_STATUS_FSYNC;
1661 mutex_unlock(&audio->lock);
1662
1663 mutex_lock(&audio->write_lock);
1664 /* pcm dmamiss message is sent continously
1665 * when decoder is starved so no race
1666 * condition concern
1667 */
1668 audio->teos = 0;
1669
1670 rc = wait_event_interruptible(audio->write_wait,
1671 (audio->teos && audio->out_needed &&
1672 list_empty(&audio->out_queue))
1673 || audio->wflush || audio->stopped);
1674
1675 if (audio->stopped || audio->wflush)
1676 rc = -EBUSY;
1677
1678 mutex_unlock(&audio->write_lock);
1679 mutex_lock(&audio->lock);
1680 audio->drv_status &= ~ADRV_STATUS_FSYNC;
1681 mutex_unlock(&audio->lock);
1682
1683 return rc;
1684}
1685
1686int audmp3_sync_fsync(struct audio *audio)
1687{
1688 struct buffer *frame;
1689 int rc = 0;
1690
1691 MM_DBG("\n"); /* Macro prints the file name and function */
1692
1693 mutex_lock(&audio->write_lock);
1694
1695 rc = wait_event_interruptible(audio->write_wait,
1696 (!audio->out[0].used &&
1697 !audio->out[1].used &&
1698 audio->out_needed) || audio->wflush);
1699
1700 if (rc < 0)
1701 goto done;
1702 else if (audio->wflush) {
1703 rc = -EBUSY;
1704 goto done;
1705 }
1706
1707 if (audio->reserved) {
1708 MM_DBG("send reserved byte\n");
1709 frame = audio->out + audio->out_tail;
1710 ((char *) frame->data)[0] = audio->rsv_byte;
1711 ((char *) frame->data)[1] = 0;
1712 frame->used = 2;
1713 audio->drv_ops.send_data(audio, 0);
1714
1715 rc = wait_event_interruptible(audio->write_wait,
1716 (!audio->out[0].used &&
1717 !audio->out[1].used &&
1718 audio->out_needed) || audio->wflush);
1719
1720 if (rc < 0)
1721 goto done;
1722 else if (audio->wflush) {
1723 rc = -EBUSY;
1724 goto done;
1725 }
1726 }
1727
1728 /* pcm dmamiss message is sent continously
1729 * when decoder is starved so no race
1730 * condition concern
1731 */
1732 audio->teos = 0;
1733
1734 rc = wait_event_interruptible(audio->write_wait,
1735 audio->teos || audio->wflush);
1736
1737 if (audio->wflush)
1738 rc = -EBUSY;
1739
1740done:
1741 mutex_unlock(&audio->write_lock);
1742 return rc;
1743}
1744
Steve Mucklef132c6c2012-06-06 18:30:57 -07001745int audmp3_fsync(struct file *file, loff_t a, loff_t b, int datasync)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001746{
1747 struct audio *audio = file->private_data;
1748
1749 if (!audio->running || audio->pcm_feedback)
1750 return -EINVAL;
1751
1752 return audio->drv_ops.fsync(audio);
1753}
1754
1755static ssize_t audio_read(struct file *file, char __user *buf, size_t count,
1756 loff_t *pos)
1757{
1758 struct audio *audio = file->private_data;
1759 const char __user *start = buf;
1760 int rc = 0;
1761
1762 if (audio->drv_status & ADRV_STATUS_AIO_INTF)
1763 return -EPERM;
1764 else if (!audio->pcm_feedback)
1765 return 0; /* PCM feedback disabled. Nothing to read */
1766
1767 mutex_lock(&audio->read_lock);
1768 MM_DBG("%d \n", count);
1769 while (count > 0) {
1770 rc = wait_event_interruptible(
1771 audio->read_wait,
1772 (audio->in[audio->read_next].
1773 used > 0) || (audio->stopped)
1774 || (audio->rflush));
1775
1776 if (rc < 0)
1777 break;
1778
1779 if (audio->stopped || audio->rflush) {
1780 rc = -EBUSY;
1781 break;
1782 }
1783
1784 if (count < audio->in[audio->read_next].used) {
1785 /* Read must happen in frame boundary. Since
1786 * driver does not know frame size, read count
1787 * must be greater or equal
1788 * to size of PCM samples
1789 */
1790 MM_DBG("no partial frame done reading\n");
1791 break;
1792 } else {
1793 MM_DBG("read from in[%d]\n", audio->read_next);
1794 /* order reads from the output buffer */
1795 rmb();
1796 if (copy_to_user
1797 (buf, audio->in[audio->read_next].data,
1798 audio->in[audio->read_next].used)) {
1799 MM_ERR("invalid addr %x \n", (unsigned int)buf);
1800 rc = -EFAULT;
1801 break;
1802 }
1803 count -= audio->in[audio->read_next].used;
1804 buf += audio->in[audio->read_next].used;
1805 audio->in[audio->read_next].used = 0;
1806 if ((++audio->read_next) == audio->pcm_buf_count)
1807 audio->read_next = 0;
1808 break; /* Force to exit while loop
1809 * to prevent output thread
1810 * sleep too long if data is
1811 * not ready at this moment.
1812 */
1813 }
1814 }
1815
1816 /* don't feed output buffer to HW decoder during flushing
1817 * buffer refresh command will be sent once flush completes
1818 * send buf refresh command here can confuse HW decoder
1819 */
1820 if (audio->buf_refresh && !audio->rflush) {
1821 audio->buf_refresh = 0;
1822 MM_DBG("kick start pcm feedback again\n");
1823 audio->drv_ops.buffer_refresh(audio);
1824 }
1825
1826 mutex_unlock(&audio->read_lock);
1827
1828 if (buf > start)
1829 rc = buf - start;
1830
1831 MM_DBG("read %d bytes\n", rc);
1832 return rc;
1833}
1834
1835static int audmp3_process_eos(struct audio *audio,
1836 const char __user *buf_start, unsigned short mfield_size)
1837{
1838 int rc = 0;
1839 struct buffer *frame;
1840 char *buf_ptr;
1841
1842 if (audio->reserved) {
1843 MM_DBG("flush reserve byte\n");
1844 frame = audio->out + audio->out_head;
1845 buf_ptr = frame->data;
1846 rc = wait_event_interruptible(audio->write_wait,
1847 (frame->used == 0)
1848 || (audio->stopped)
1849 || (audio->wflush));
1850 if (rc < 0)
1851 goto done;
1852 if (audio->stopped || audio->wflush) {
1853 rc = -EBUSY;
1854 goto done;
1855 }
1856
1857 buf_ptr[0] = audio->rsv_byte;
1858 buf_ptr[1] = 0;
1859 audio->out_head ^= 1;
1860 frame->mfield_sz = 0;
1861 frame->used = 2;
1862 audio->reserved = 0;
1863 audio->drv_ops.send_data(audio, 0);
1864 }
1865
1866 frame = audio->out + audio->out_head;
1867
1868 rc = wait_event_interruptible(audio->write_wait,
1869 (audio->out_needed &&
1870 audio->out[0].used == 0 &&
1871 audio->out[1].used == 0)
1872 || (audio->stopped)
1873 || (audio->wflush));
1874
1875 if (rc < 0)
1876 goto done;
1877 if (audio->stopped || audio->wflush) {
1878 rc = -EBUSY;
1879 goto done;
1880 }
1881
1882 if (copy_from_user(frame->data, buf_start, mfield_size)) {
1883 rc = -EFAULT;
1884 goto done;
1885 }
1886
1887 frame->mfield_sz = mfield_size;
1888 audio->out_head ^= 1;
1889 frame->used = mfield_size;
1890 audio->drv_ops.send_data(audio, 0);
1891done:
1892 return rc;
1893}
1894
1895static ssize_t audio_write(struct file *file, const char __user *buf,
1896 size_t count, loff_t *pos)
1897{
1898 struct audio *audio = file->private_data;
1899 const char __user *start = buf;
1900 struct buffer *frame;
1901 size_t xfer;
1902 char *cpy_ptr;
1903 int rc = 0, eos_condition = AUDMP3_EOS_NONE;
1904 unsigned dsize;
1905 unsigned short mfield_size = 0;
1906
1907 if (audio->drv_status & ADRV_STATUS_AIO_INTF)
1908 return -EPERM;
1909
1910 MM_DBG("cnt=%d\n", count);
1911
1912 mutex_lock(&audio->write_lock);
1913 while (count > 0) {
1914 frame = audio->out + audio->out_head;
1915 cpy_ptr = frame->data;
1916 dsize = 0;
1917 rc = wait_event_interruptible(audio->write_wait,
1918 (frame->used == 0)
1919 || (audio->stopped)
1920 || (audio->wflush));
1921 if (rc < 0)
1922 break;
1923 if (audio->stopped || audio->wflush) {
1924 rc = -EBUSY;
1925 break;
1926 }
1927 if (audio->mfield) {
1928 if (buf == start) {
1929 /* Processing beginning of user buffer */
1930 if (__get_user(mfield_size,
1931 (unsigned short __user *) buf)) {
1932 rc = -EFAULT;
1933 break;
1934 } else if (mfield_size > count) {
1935 rc = -EINVAL;
1936 break;
1937 }
1938 MM_DBG("mf offset_val %x\n", mfield_size);
1939 if (copy_from_user(cpy_ptr, buf, mfield_size)) {
1940 rc = -EFAULT;
1941 break;
1942 }
1943 /* Check if EOS flag is set and buffer has
1944 * contains just meta field
1945 */
1946 if (cpy_ptr[AUDMP3_EOS_FLG_OFFSET] &
1947 AUDMP3_EOS_FLG_MASK) {
1948 MM_DBG("EOS SET\n");
1949 eos_condition = AUDMP3_EOS_SET;
1950 if (mfield_size == count) {
1951 buf += mfield_size;
1952 break;
1953 } else
1954 cpy_ptr[AUDMP3_EOS_FLG_OFFSET]
1955 &= ~AUDMP3_EOS_FLG_MASK;
1956 }
1957 cpy_ptr += mfield_size;
1958 count -= mfield_size;
1959 dsize += mfield_size;
1960 buf += mfield_size;
1961 } else {
1962 mfield_size = 0;
1963 MM_DBG("continuous buffer\n");
1964 }
1965 frame->mfield_sz = mfield_size;
1966 }
1967
1968 if (audio->reserved) {
1969 MM_DBG("append reserved byte %x\n", audio->rsv_byte);
1970 *cpy_ptr = audio->rsv_byte;
1971 xfer = (count > ((frame->size - mfield_size) - 1)) ?
1972 (frame->size - mfield_size) - 1 : count;
1973 cpy_ptr++;
1974 dsize += 1;
1975 audio->reserved = 0;
1976 } else
1977 xfer = (count > (frame->size - mfield_size)) ?
1978 (frame->size - mfield_size) : count;
1979
1980 if (copy_from_user(cpy_ptr, buf, xfer)) {
1981 rc = -EFAULT;
1982 break;
1983 }
1984
1985 dsize += xfer;
1986 if (dsize & 1) {
1987 audio->rsv_byte = ((char *) frame->data)[dsize - 1];
1988 MM_DBG("odd length buf reserve last byte %x\n",
1989 audio->rsv_byte);
1990 audio->reserved = 1;
1991 dsize--;
1992 }
1993 count -= xfer;
1994 buf += xfer;
1995
1996 if (dsize > 0) {
1997 audio->out_head ^= 1;
1998 frame->used = dsize;
1999 audio->drv_ops.send_data(audio, 0);
2000 }
2001 }
2002 if (eos_condition == AUDMP3_EOS_SET)
2003 rc = audmp3_process_eos(audio, start, mfield_size);
2004 mutex_unlock(&audio->write_lock);
2005 if (!rc) {
2006 if (buf > start)
2007 return buf - start;
2008 }
2009 return rc;
2010}
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302011static void audmp3_reset_ion_region(struct audio *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002012{
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302013 struct audmp3_ion_region *region;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002014 struct list_head *ptr, *next;
2015
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302016 list_for_each_safe(ptr, next, &audio->ion_region_queue) {
2017 region = list_entry(ptr, struct audmp3_ion_region, list);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002018 list_del(&region->list);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302019 ion_unmap_kernel(audio->client, region->handle);
2020 ion_free(audio->client, region->handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002021 kfree(region);
2022 }
2023
2024 return;
2025}
2026
2027static int audio_release(struct inode *inode, struct file *file)
2028{
2029 struct audio *audio = file->private_data;
2030
2031 MM_INFO("audio instance 0x%08x freeing\n", (int)audio);
2032 mutex_lock(&audio->lock);
2033 audio_disable(audio);
2034 if (audio->rmt_resource_released == 0)
2035 rmt_put_resource(audio);
2036 audio->drv_ops.out_flush(audio);
2037 audio->drv_ops.in_flush(audio);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302038 audmp3_reset_ion_region(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002039
2040 msm_adsp_put(audio->audplay);
2041 audpp_adec_free(audio->dec_id);
2042#ifdef CONFIG_HAS_EARLYSUSPEND
2043 unregister_early_suspend(&audio->suspend_ctl.node);
2044#endif
2045 audio->opened = 0;
2046 audio->event_abort = 1;
2047 wake_up(&audio->event_wait);
2048 audmp3_reset_event_queue(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002049 mutex_unlock(&audio->lock);
2050#ifdef CONFIG_DEBUG_FS
2051 if (audio->dentry)
2052 debugfs_remove(audio->dentry);
2053#endif
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302054 if (!(audio->drv_status & ADRV_STATUS_AIO_INTF)) {
2055 ion_unmap_kernel(audio->client, audio->output_buff_handle);
2056 ion_free(audio->client, audio->output_buff_handle);
2057 ion_unmap_kernel(audio->client, audio->input_buff_handle);
2058 ion_free(audio->client, audio->input_buff_handle);
2059 }
2060 ion_client_destroy(audio->client);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002061 kfree(audio);
2062 return 0;
2063}
2064
2065static void audmp3_post_event(struct audio *audio, int type,
2066 union msm_audio_event_payload payload)
2067{
2068 struct audmp3_event *e_node = NULL;
2069 unsigned long flags;
2070
2071 spin_lock_irqsave(&audio->event_queue_lock, flags);
2072
2073 if (!list_empty(&audio->free_event_queue)) {
2074 e_node = list_first_entry(&audio->free_event_queue,
2075 struct audmp3_event, list);
2076 list_del(&e_node->list);
2077 } else {
2078 e_node = kmalloc(sizeof(struct audmp3_event), GFP_ATOMIC);
2079 if (!e_node) {
2080 MM_ERR("No mem to post event %d\n", type);
2081 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
2082 return;
2083 }
2084 }
2085
2086 e_node->event_type = type;
2087 e_node->payload = payload;
2088
2089 list_add_tail(&e_node->list, &audio->event_queue);
2090 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
2091 wake_up(&audio->event_wait);
2092}
2093
2094#ifdef CONFIG_HAS_EARLYSUSPEND
2095static void audmp3_suspend(struct early_suspend *h)
2096{
2097 struct audmp3_suspend_ctl *ctl =
2098 container_of(h, struct audmp3_suspend_ctl, node);
2099 union msm_audio_event_payload payload;
2100
2101 MM_DBG("\n"); /* Macro prints the file name and function */
2102 audmp3_post_event(ctl->audio, AUDIO_EVENT_SUSPEND, payload);
2103}
2104
2105static void audmp3_resume(struct early_suspend *h)
2106{
2107 struct audmp3_suspend_ctl *ctl =
2108 container_of(h, struct audmp3_suspend_ctl, node);
2109 union msm_audio_event_payload payload;
2110
2111 MM_DBG("\n"); /* Macro prints the file name and function */
2112 audmp3_post_event(ctl->audio, AUDIO_EVENT_RESUME, payload);
2113}
2114#endif
2115
2116#ifdef CONFIG_DEBUG_FS
2117static ssize_t audmp3_debug_open(struct inode *inode, struct file *file)
2118{
2119 file->private_data = inode->i_private;
2120 return 0;
2121}
2122
2123static ssize_t audmp3_debug_read(struct file *file, char __user *buf,
2124 size_t count, loff_t *ppos)
2125{
2126 const int debug_bufmax = 4096;
2127 static char buffer[4096];
2128 int n = 0, i;
2129 struct audio *audio = file->private_data;
2130
2131 mutex_lock(&audio->lock);
2132 n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
2133 n += scnprintf(buffer + n, debug_bufmax - n,
2134 "enabled %d\n", audio->enabled);
2135 n += scnprintf(buffer + n, debug_bufmax - n,
2136 "stopped %d\n", audio->stopped);
2137 n += scnprintf(buffer + n, debug_bufmax - n,
2138 "pcm_feedback %d\n", audio->pcm_feedback);
2139 n += scnprintf(buffer + n, debug_bufmax - n,
2140 "out_buf_sz %d\n", audio->out[0].size);
2141 n += scnprintf(buffer + n, debug_bufmax - n,
2142 "pcm_buf_count %d \n", audio->pcm_buf_count);
2143 n += scnprintf(buffer + n, debug_bufmax - n,
2144 "pcm_buf_sz %d \n", audio->in[0].size);
2145 n += scnprintf(buffer + n, debug_bufmax - n,
2146 "volume %x \n", audio->vol_pan.volume);
2147 n += scnprintf(buffer + n, debug_bufmax - n,
2148 "sample rate %d \n", audio->out_sample_rate);
2149 n += scnprintf(buffer + n, debug_bufmax - n,
2150 "channel mode %d \n", audio->out_channel_mode);
2151 mutex_unlock(&audio->lock);
2152 /* Following variables are only useful for debugging when
2153 * when playback halts unexpectedly. Thus, no mutual exclusion
2154 * enforced
2155 */
2156 n += scnprintf(buffer + n, debug_bufmax - n,
2157 "wflush %d\n", audio->wflush);
2158 n += scnprintf(buffer + n, debug_bufmax - n,
2159 "rflush %d\n", audio->rflush);
2160 n += scnprintf(buffer + n, debug_bufmax - n,
2161 "running %d \n", audio->running);
2162 n += scnprintf(buffer + n, debug_bufmax - n,
2163 "dec state %d \n", audio->dec_state);
2164 n += scnprintf(buffer + n, debug_bufmax - n,
2165 "out_needed %d \n", audio->out_needed);
2166 n += scnprintf(buffer + n, debug_bufmax - n,
2167 "out_head %d \n", audio->out_head);
2168 n += scnprintf(buffer + n, debug_bufmax - n,
2169 "out_tail %d \n", audio->out_tail);
2170 n += scnprintf(buffer + n, debug_bufmax - n,
2171 "out[0].used %d \n", audio->out[0].used);
2172 n += scnprintf(buffer + n, debug_bufmax - n,
2173 "out[1].used %d \n", audio->out[1].used);
2174 n += scnprintf(buffer + n, debug_bufmax - n,
2175 "buffer_refresh %d \n", audio->buf_refresh);
2176 n += scnprintf(buffer + n, debug_bufmax - n,
2177 "read_next %d \n", audio->read_next);
2178 n += scnprintf(buffer + n, debug_bufmax - n,
2179 "fill_next %d \n", audio->fill_next);
2180 for (i = 0; i < audio->pcm_buf_count; i++)
2181 n += scnprintf(buffer + n, debug_bufmax - n,
2182 "in[%d].size %d \n", i, audio->in[i].used);
2183 buffer[n] = 0;
2184 return simple_read_from_buffer(buf, count, ppos, buffer, n);
2185}
2186
2187static const struct file_operations audmp3_debug_fops = {
2188 .read = audmp3_debug_read,
2189 .open = audmp3_debug_open,
2190};
2191#endif
2192
2193static int audio_open(struct inode *inode, struct file *file)
2194{
2195
2196 struct audio *audio = NULL;
2197 int rc, i, dec_attrb, decid;
2198 struct audmp3_event *e_node = NULL;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302199 unsigned mem_sz = DMASZ_MAX;
2200 unsigned long ionflag = 0;
2201 ion_phys_addr_t addr = 0;
2202 struct ion_handle *handle = NULL;
2203 struct ion_client *client = NULL;
2204 int len = 0;
2205
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002206#ifdef CONFIG_DEBUG_FS
2207 /* 4 bytes represents decoder number, 1 byte for terminate string */
2208 char name[sizeof "msm_mp3_" + 5];
2209#endif
2210
2211 /* Allocate audio instance, set to zero */
2212 audio = kzalloc(sizeof(struct audio), GFP_KERNEL);
2213 if (!audio) {
2214 MM_ERR("no memory to allocate audio instance \n");
2215 rc = -ENOMEM;
2216 goto done;
2217 }
2218 MM_INFO("audio instance 0x%08x created\n", (int)audio);
2219
2220 /* Allocate the decoder */
2221 dec_attrb = AUDDEC_DEC_MP3;
2222 if ((file->f_mode & FMODE_WRITE) &&
2223 (file->f_mode & FMODE_READ)) {
2224 dec_attrb |= MSM_AUD_MODE_NONTUNNEL;
2225 audio->pcm_feedback = NON_TUNNEL_MODE_PLAYBACK;
2226 } else if ((file->f_mode & FMODE_WRITE) &&
2227 !(file->f_mode & FMODE_READ)) {
2228 dec_attrb |= MSM_AUD_MODE_TUNNEL;
2229 audio->pcm_feedback = TUNNEL_MODE_PLAYBACK;
2230 } else {
2231 kfree(audio);
2232 rc = -EACCES;
2233 goto done;
2234 }
2235
2236 decid = audpp_adec_alloc(dec_attrb, &audio->module_name,
2237 &audio->queue_id);
2238 if (decid < 0) {
2239 MM_ERR("No free decoder available, freeing instance 0x%08x\n",
2240 (int)audio);
2241 rc = -ENODEV;
2242 kfree(audio);
2243 goto done;
2244 }
2245 audio->dec_id = decid & MSM_AUD_DECODER_MASK;
2246
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302247 client = msm_ion_client_create(UINT_MAX, "Audio_MP3_Client");
2248 if (IS_ERR_OR_NULL(client)) {
2249 pr_err("Unable to create ION client\n");
2250 rc = -ENOMEM;
2251 goto client_create_error;
2252 }
2253 audio->client = client;
2254
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002255 /* Non AIO interface */
2256 if (!(file->f_flags & O_NONBLOCK)) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302257
2258 MM_DBG("memsz = %d\n", mem_sz);
2259
2260 handle = ion_alloc(client, mem_sz, SZ_4K,
Hanumant Singh7d72bad2012-08-29 18:39:44 -07002261 ION_HEAP(ION_AUDIO_HEAP_ID), 0);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302262 if (IS_ERR_OR_NULL(handle)) {
2263 MM_ERR("Unable to create allocate O/P buffers\n");
2264 rc = -ENOMEM;
2265 goto output_buff_alloc_error;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002266 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302267 audio->output_buff_handle = handle;
2268
2269 rc = ion_phys(client , handle, &addr, &len);
2270 if (rc) {
2271 MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
2272 (unsigned int) addr, (unsigned int) len);
2273 goto output_buff_get_phys_error;
2274 } else {
2275 MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
2276 (unsigned int) addr, (unsigned int) len);
2277 }
2278 audio->phys = (int32_t)addr;
2279
2280
2281 rc = ion_handle_get_flags(client, handle, &ionflag);
2282 if (rc) {
2283 MM_ERR("could not get flags for the handle\n");
2284 goto output_buff_get_flags_error;
2285 }
2286
Mitchel Humpherys911b4b72012-09-12 14:42:50 -07002287 audio->map_v_write = ion_map_kernel(client, handle);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302288 if (IS_ERR(audio->map_v_write)) {
2289 MM_ERR("could not map write buffers\n");
2290 rc = -ENOMEM;
2291 goto output_buff_map_error;
2292 }
2293 audio->data = audio->map_v_write;
2294 MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
2295 audio->phys, (int)audio->data);
2296
2297 audio->out_dma_sz = mem_sz;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002298 }
2299
2300 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
2301 rc = audmgr_open(&audio->audmgr);
2302 if (rc) {
2303 MM_ERR("audmgr open failed, freeing instance \
2304 0x%08x\n", (int)audio);
Chaithanya Krishna Bacharajud0989382012-09-03 18:34:49 +05302305 if (!(file->f_flags & O_NONBLOCK))
2306 goto err;
2307 else
2308 goto resource_err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002309 }
2310 }
2311
2312 rc = msm_adsp_get(audio->module_name, &audio->audplay,
2313 &audplay_adsp_ops, audio);
2314
2315 if (rc) {
2316 MM_ERR("failed to get %s module, freeing instance 0x%08x\n",
2317 audio->module_name, (int)audio);
2318 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
2319 audmgr_close(&audio->audmgr);
Chaithanya Krishna Bacharajud0989382012-09-03 18:34:49 +05302320 if (!(file->f_flags & O_NONBLOCK))
2321 goto err;
2322 else
2323 goto resource_err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002324 }
2325
2326 rc = rmt_get_resource(audio);
2327 if (rc) {
2328 MM_ERR("ADSP resources are not available for MP3 session \
2329 0x%08x on decoder: %d\n", (int)audio, audio->dec_id);
2330 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
2331 audmgr_close(&audio->audmgr);
2332 msm_adsp_put(audio->audplay);
Chaithanya Krishna Bacharajud0989382012-09-03 18:34:49 +05302333 if (!(file->f_flags & O_NONBLOCK))
2334 goto err;
2335 else
2336 goto resource_err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002337 }
2338
2339 if (file->f_flags & O_NONBLOCK) {
2340 MM_DBG("set to aio interface\n");
2341 audio->drv_status |= ADRV_STATUS_AIO_INTF;
2342 audio->drv_ops.pcm_buf_update = audmp3_async_pcm_buf_update;
2343 audio->drv_ops.buffer_refresh = audmp3_async_buffer_refresh;
2344 audio->drv_ops.send_data = audmp3_async_send_data;
2345 audio->drv_ops.out_flush = audmp3_async_flush;
2346 audio->drv_ops.in_flush = audmp3_async_flush_pcm_buf;
2347 audio->drv_ops.fsync = audmp3_async_fsync;
2348 } else {
2349 MM_DBG("set to std io interface\n");
2350 audio->drv_ops.pcm_buf_update = audio_update_pcm_buf_entry;
2351 audio->drv_ops.buffer_refresh = audplay_buffer_refresh;
2352 audio->drv_ops.send_data = audplay_send_data;
2353 audio->drv_ops.out_flush = audio_flush;
2354 audio->drv_ops.in_flush = audio_flush_pcm_buf;
2355 audio->drv_ops.fsync = audmp3_sync_fsync;
2356 audio->out[0].data = audio->data + 0;
2357 audio->out[0].addr = audio->phys + 0;
2358 audio->out[0].size = (audio->out_dma_sz >> 1);
2359
2360 audio->out[1].data = audio->data + audio->out[0].size;
2361 audio->out[1].addr = audio->phys + audio->out[0].size;
2362 audio->out[1].size = audio->out[0].size;
2363 }
2364
2365 /* Initialize all locks of audio instance */
2366 mutex_init(&audio->lock);
2367 mutex_init(&audio->write_lock);
2368 mutex_init(&audio->read_lock);
2369 mutex_init(&audio->get_event_lock);
2370 spin_lock_init(&audio->dsp_lock);
2371 init_waitqueue_head(&audio->write_wait);
2372 init_waitqueue_head(&audio->read_wait);
2373 INIT_LIST_HEAD(&audio->out_queue);
2374 INIT_LIST_HEAD(&audio->in_queue);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302375 INIT_LIST_HEAD(&audio->ion_region_queue);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002376 INIT_LIST_HEAD(&audio->free_event_queue);
2377 INIT_LIST_HEAD(&audio->event_queue);
2378 init_waitqueue_head(&audio->wait);
2379 init_waitqueue_head(&audio->event_wait);
2380 spin_lock_init(&audio->event_queue_lock);
2381
2382 audio->out_sample_rate = 44100;
2383 audio->out_channel_mode = AUDPP_CMD_PCM_INTF_STEREO_V;
2384 audio->vol_pan.volume = 0x2000;
2385
2386 audio->drv_ops.out_flush(audio);
2387
2388 file->private_data = audio;
2389 audio->opened = 1;
2390#ifdef CONFIG_DEBUG_FS
2391 snprintf(name, sizeof name, "msm_mp3_%04x", audio->dec_id);
2392 audio->dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
2393 NULL, (void *) audio, &audmp3_debug_fops);
2394
2395 if (IS_ERR(audio->dentry))
2396 MM_DBG("debugfs_create_file failed\n");
2397#endif
2398#ifdef CONFIG_HAS_EARLYSUSPEND
2399 audio->suspend_ctl.node.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
2400 audio->suspend_ctl.node.resume = audmp3_resume;
2401 audio->suspend_ctl.node.suspend = audmp3_suspend;
2402 audio->suspend_ctl.audio = audio;
2403 register_early_suspend(&audio->suspend_ctl.node);
2404#endif
2405 for (i = 0; i < AUDMP3_EVENT_NUM; i++) {
2406 e_node = kmalloc(sizeof(struct audmp3_event), GFP_KERNEL);
2407 if (e_node)
2408 list_add_tail(&e_node->list, &audio->free_event_queue);
2409 else {
2410 MM_ERR("event pkt alloc failed\n");
2411 break;
2412 }
2413 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302414
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002415done:
2416 return rc;
2417err:
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05302418 ion_unmap_kernel(client, audio->output_buff_handle);
2419output_buff_map_error:
2420output_buff_get_flags_error:
2421output_buff_get_phys_error:
2422 ion_free(client, audio->output_buff_handle);
2423output_buff_alloc_error:
2424 ion_client_destroy(client);
2425client_create_error:
Chaithanya Krishna Bacharajud0989382012-09-03 18:34:49 +05302426resource_err:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002427 audpp_adec_free(audio->dec_id);
2428 kfree(audio);
2429 return rc;
2430}
2431
2432static const struct file_operations audio_mp3_fops = {
2433 .owner = THIS_MODULE,
2434 .open = audio_open,
2435 .release = audio_release,
2436 .read = audio_read,
2437 .write = audio_write,
2438 .unlocked_ioctl = audio_ioctl,
2439 .fsync = audmp3_fsync,
2440};
2441
2442struct miscdevice audio_mp3_misc = {
2443 .minor = MISC_DYNAMIC_MINOR,
2444 .name = "msm_mp3",
2445 .fops = &audio_mp3_fops,
2446};
2447
2448static int __init audio_init(void)
2449{
2450 return misc_register(&audio_mp3_misc);
2451}
2452
2453static void __exit audio_exit(void)
2454{
2455 misc_deregister(&audio_mp3_misc);
2456}
2457
2458module_init(audio_init);
2459module_exit(audio_exit);
2460
2461MODULE_DESCRIPTION("MSM MP3 driver");
2462MODULE_LICENSE("GPL v2");